Merge "Make home stack move like another stack."
diff --git a/Android.mk b/Android.mk
index f1e16b8..9029f4e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -483,6 +483,7 @@
frameworks/base/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/WpsInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/ScanResult.aidl \
+ frameworks/base/wifi/java/android/net/wifi/ScanInfo.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiEnterpriseConfig.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.aidl \
frameworks/base/wifi/java/android/net/wifi/WifiInfo.aidl \
diff --git a/api/current.txt b/api/current.txt
index 00b5ec0..c9e9f9a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -779,6 +779,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
+ field public static final int level = 16844031; // 0x10104ff
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -18250,6 +18251,7 @@
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -19156,6 +19158,22 @@
package android.net.wifi {
+ public class ScanInfo implements android.os.Parcelable {
+ ctor public ScanInfo(android.net.wifi.ScanResult);
+ ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
+ method public int describeContents();
+ method public long getBssid();
+ method public byte[] getIconData();
+ method public java.lang.String getIconType();
+ method public java.lang.String getName();
+ method public int getOsuIdentity();
+ method public int getRssi();
+ method public android.net.wifi.ScanResult getScanResult();
+ method public java.lang.String getServiceDescription();
+ method public java.lang.String getSsid();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -19356,6 +19374,7 @@
method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
+ method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -19371,6 +19390,7 @@
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
+ method public void setOsuSelection(int);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -40972,6 +40992,7 @@
method public void setInterpolator(android.view.animation.Interpolator);
method public synchronized void setMax(int);
method public synchronized void setProgress(int);
+ method public void setProgress(int, boolean);
method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode);
method public void setProgressDrawable(android.graphics.drawable.Drawable);
diff --git a/api/system-current.txt b/api/system-current.txt
index b2803b7..f39dc9a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -871,6 +871,7 @@
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
field public static final int letterSpacing = 16843958; // 0x10104b6
+ field public static final int level = 16844031; // 0x10104ff
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -19762,6 +19763,7 @@
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+ field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
@@ -20909,6 +20911,22 @@
field public byte id;
}
+ public class ScanInfo implements android.os.Parcelable {
+ ctor public ScanInfo(android.net.wifi.ScanResult);
+ ctor public ScanInfo(long, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String, byte[], int);
+ method public int describeContents();
+ method public long getBssid();
+ method public byte[] getIconData();
+ method public java.lang.String getIconType();
+ method public java.lang.String getName();
+ method public int getOsuIdentity();
+ method public int getRssi();
+ method public android.net.wifi.ScanResult getScanResult();
+ method public java.lang.String getServiceDescription();
+ method public java.lang.String getSsid();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
method public boolean is80211mcResponder();
@@ -21134,6 +21152,7 @@
method public android.net.wifi.WifiConnectionStatistics getConnectionStatistics();
method public android.net.DhcpInfo getDhcpInfo();
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
+ method public java.util.List<android.net.wifi.ScanInfo> getScanInfos();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
@@ -21153,6 +21172,7 @@
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
+ method public void setOsuSelection(int);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
@@ -25667,8 +25687,8 @@
ctor public UserHandle(android.os.Parcel);
method public int describeContents();
method public int getIdentifier();
- method public final boolean isOwner();
- method public static final int myUserId();
+ method public boolean isOwner();
+ method public static int myUserId();
method public static android.os.UserHandle readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
method public static void writeToParcel(android.os.UserHandle, android.os.Parcel);
@@ -43580,6 +43600,7 @@
method public void setInterpolator(android.view.animation.Interpolator);
method public synchronized void setMax(int);
method public synchronized void setProgress(int);
+ method public void setProgress(int, boolean);
method public void setProgressBackgroundTintList(android.content.res.ColorStateList);
method public void setProgressBackgroundTintMode(android.graphics.PorterDuff.Mode);
method public void setProgressDrawable(android.graphics.drawable.Drawable);
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index d1e40ae..4e9adf0 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -20,6 +20,7 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -360,6 +361,7 @@
/**
* Return the component of the receiver that implements this device admin.
*/
+ @NonNull
public ComponentName getComponent() {
return new ComponentName(mReceiver.activityInfo.packageName,
mReceiver.activityInfo.name);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 7392563..d7c2215 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -136,7 +136,16 @@
* the method always returns false.
*/
public boolean isSystemOnly() {
- return id == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
+ return isSystemOnly(id);
+ }
+
+ /**
+ * Returns true if the given user is a split system user.
+ * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
+ * the method always returns false.
+ */
+ public static boolean isSystemOnly(int userId) {
+ return userId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
}
/**
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 927c02f..477b62c 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -61,7 +61,7 @@
* resource qualifier. 0 if undefined.
*/
public int mcc;
-
+
/**
* IMSI MNC (Mobile Network Code), corresponding to
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#MccQualifier">mnc</a>
@@ -199,7 +199,7 @@
* @hide
*/
public static final int SCREENLAYOUT_COMPAT_NEEDED = 0x10000000;
-
+
/**
* Bit mask of overall layout of the screen. Currently there are two
* fields:
@@ -207,11 +207,11 @@
* of the screen. They may be one of
* {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
* {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
- *
+ *
* <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
* is wider/taller than normal. They may be one of
* {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
- *
+ *
* <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
* is either LTR or RTL. They may be one of
* {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
@@ -295,6 +295,62 @@
return curLayout;
}
+ /** @hide */
+ public static String configurationDiffToString(int diff) {
+ ArrayList<String> list = new ArrayList<>();
+ if ((diff & ActivityInfo.CONFIG_MCC) != 0) {
+ list.add("CONFIG_MCC");
+ }
+ if ((diff & ActivityInfo.CONFIG_MNC) != 0) {
+ list.add("CONFIG_MNC");
+ }
+ if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) {
+ list.add("CONFIG_LOCALE");
+ }
+ if ((diff & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
+ list.add("CONFIG_TOUCHSCREEN");
+ }
+ if ((diff & ActivityInfo.CONFIG_KEYBOARD) != 0) {
+ list.add("CONFIG_KEYBOARD");
+ }
+ if ((diff & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
+ list.add("CONFIG_KEYBOARD_HIDDEN");
+ }
+ if ((diff & ActivityInfo.CONFIG_NAVIGATION) != 0) {
+ list.add("CONFIG_NAVIGATION");
+ }
+ if ((diff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+ list.add("CONFIG_ORIENTATION");
+ }
+ if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
+ list.add("CONFIG_SCREEN_LAYOUT");
+ }
+ if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
+ list.add("CONFIG_UI_MODE");
+ }
+ if ((diff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
+ list.add("CONFIG_SCREEN_SIZE");
+ }
+ if ((diff & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
+ list.add("CONFIG_SMALLEST_SCREEN_SIZE");
+ }
+ if ((diff & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
+ list.add("CONFIG_LAYOUT_DIRECTION");
+ }
+ if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
+ list.add("CONFIG_FONT_SCALE");
+ }
+ StringBuilder builder = new StringBuilder("{");
+ for (int i = 0, n = list.size(); i < n; i++) {
+ builder.append(list.get(i));
+ if (i != n - 1) {
+ builder.append(", ");
+ }
+ }
+ builder.append("}");
+ return builder.toString();
+ }
+
/**
* Check if the Configuration's current {@link #screenLayout} is at
* least the given size.
@@ -323,7 +379,7 @@
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a>
* resource qualifier. */
public static final int TOUCHSCREEN_FINGER = 3;
-
+
/**
* The kind of touch screen attached to the device.
* One of: {@link #TOUCHSCREEN_NOTOUCH}, {@link #TOUCHSCREEN_FINGER}.
@@ -344,7 +400,7 @@
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#ImeQualifier">12key</a>
* resource qualifier. */
public static final int KEYBOARD_12KEY = 3;
-
+
/**
* The kind of keyboard attached to the device.
* One of: {@link #KEYBOARD_NOKEYS}, {@link #KEYBOARD_QWERTY},
@@ -364,7 +420,7 @@
public static final int KEYBOARDHIDDEN_YES = 2;
/** Constant matching actual resource implementation. {@hide} */
public static final int KEYBOARDHIDDEN_SOFT = 3;
-
+
/**
* A flag indicating whether any keyboard is available. Unlike
* {@link #hardKeyboardHidden}, this also takes into account a soft
@@ -373,7 +429,7 @@
* {@link #KEYBOARDHIDDEN_NO}, {@link #KEYBOARDHIDDEN_YES}.
*/
public int keyboardHidden;
-
+
/** Constant for {@link #hardKeyboardHidden}: a value indicating that no value has been set. */
public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0;
/** Constant for {@link #hardKeyboardHidden}, value corresponding to the
@@ -382,7 +438,7 @@
/** Constant for {@link #hardKeyboardHidden}, value corresponding to the
* physical keyboard being hidden. */
public static final int HARDKEYBOARDHIDDEN_YES = 2;
-
+
/**
* A flag indicating whether the hard keyboard has been hidden. This will
* be set on a device with a mechanism to hide the keyboard from the
@@ -390,7 +446,7 @@
* {@link #HARDKEYBOARDHIDDEN_NO}, {@link #HARDKEYBOARDHIDDEN_YES}.
*/
public int hardKeyboardHidden;
-
+
/** Constant for {@link #navigation}: a value indicating that no value has been set. */
public static final int NAVIGATION_UNDEFINED = 0;
/** Constant for {@link #navigation}, value corresponding to the
@@ -409,14 +465,14 @@
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a>
* resource qualifier. */
public static final int NAVIGATION_WHEEL = 4;
-
+
/**
* The kind of navigation method available on the device.
* One of: {@link #NAVIGATION_NONAV}, {@link #NAVIGATION_DPAD},
* {@link #NAVIGATION_TRACKBALL}, {@link #NAVIGATION_WHEEL}.
*/
public int navigation;
-
+
/** Constant for {@link #navigationHidden}: a value indicating that no value has been set. */
public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
/** Constant for {@link #navigationHidden}, value corresponding to the
@@ -427,7 +483,7 @@
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a>
* resource qualifier. */
public static final int NAVIGATIONHIDDEN_YES = 2;
-
+
/**
* A flag indicating whether any 5-way or DPAD navigation available.
* This will be set on a device with a mechanism to hide the navigation
@@ -435,7 +491,7 @@
* {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
*/
public int navigationHidden;
-
+
/** Constant for {@link #orientation}: a value indicating that no value has been set. */
public static final int ORIENTATION_UNDEFINED = 0;
/** Constant for {@link #orientation}, value corresponding to the
@@ -448,7 +504,7 @@
public static final int ORIENTATION_LANDSCAPE = 2;
/** @deprecated Not currently supported or used. */
@Deprecated public static final int ORIENTATION_SQUARE = 3;
-
+
/**
* Overall orientation of the screen. May be one of
* {@link #ORIENTATION_LANDSCAPE}, {@link #ORIENTATION_PORTRAIT}.
@@ -692,7 +748,7 @@
compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
seq = o.seq;
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("{");
@@ -861,7 +917,7 @@
@Deprecated public void makeDefault() {
setToDefaults();
}
-
+
/**
* Copy the fields from delta into this Configuration object, keeping
* track of which ones have changed. Any undefined fields in
@@ -1001,7 +1057,7 @@
if (delta.seq != 0) {
seq = delta.seq;
}
-
+
return changed;
}
@@ -1119,12 +1175,12 @@
/**
* Determine if a new resource needs to be loaded from the bit set of
* configuration changes returned by {@link #updateFrom(Configuration)}.
- *
+ *
* @param configChanges The mask of changes configurations as returned by
* {@link #updateFrom(Configuration)}.
* @param interestingChanges The configuration changes that the resource
* can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
- *
+ *
* @return Return true if the resource needs to be loaded, else false.
*/
public static boolean needNewResources(int configChanges, int interestingChanges) {
@@ -1159,7 +1215,7 @@
}
return diff > 0;
}
-
+
/**
* Parcelable methods
*/
@@ -1236,7 +1292,7 @@
compatSmallestScreenWidthDp = source.readInt();
seq = source.readInt();
}
-
+
public static final Parcelable.Creator<Configuration> CREATOR
= new Parcelable.Creator<Configuration>() {
public Configuration createFromParcel(Parcel source) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 9a2a241..444548f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -208,6 +208,12 @@
* {@link android.content.Intent#getParcelableExtra(String)}.
*/
public static final String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
+
+ /**
+ * Key for passing a URL to the captive portal login activity.
+ */
+ public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
+
/**
* Broadcast action to indicate the change of data activity status
* (idle or active) on a network in a recent period.
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index a939cce..3f36d65 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -245,7 +245,8 @@
intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
// A scorer should never become active if its package doesn't hold SCORE_NETWORKS, but
// ensure the package still holds it to be extra safe.
- mContext.sendBroadcastAsUser(intent, UserHandle.OWNER, Manifest.permission.SCORE_NETWORKS);
+ // TODO: http://b/23422763
+ mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM, Manifest.permission.SCORE_NETWORKS);
return true;
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 8c544f4..41de579 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -410,7 +410,7 @@
Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
+ context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,
android.Manifest.permission.MASTER_CLEAR,
new BroadcastReceiver() {
@Override
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 87ce12c..8b2c74f 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1923,7 +1923,7 @@
if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 30000) {
- String front = info.crashInfo.stackTrace.substring(256);
+ String front = info.crashInfo.stackTrace.substring(0, 256);
// 30000 characters is way too large for this to be any sane kind of
// strict mode collection of stacks. We've had a problem where we leave
// strict mode violations associated with the thread, and it keeps tacking
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 6888594..c368e5a 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,6 +438,8 @@
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE_DOCUMENT_ROOT);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, true);
return intent;
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 59609f9..1a83cd5 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,9 @@
public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
/** {@hide} */
+ public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
+
+ /** {@hide} */
public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
/**
@@ -266,7 +269,7 @@
* writability of a document may change over time, for example due to
* remote access changes. This flag indicates that a document client can
* expect {@link ContentResolver#openOutputStream(Uri)} to succeed.
- *
+ *
* @see #COLUMN_FLAGS
*/
public static final int FLAG_SUPPORTS_WRITE = 1 << 1;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 45bc1df..92e473d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -226,6 +226,7 @@
@ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, to = "TYPE_VOICE_INTERACTION"),
@ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, to = "TYPE_VOICE_INTERACTION_STARTING"),
+ @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER, to = "TYPE_DOCK_DIVIDER"),
})
public int type;
@@ -565,6 +566,13 @@
public static final int TYPE_VOICE_INTERACTION_STARTING = FIRST_SYSTEM_WINDOW+33;
/**
+ * Window for displaying a handle used for resizing docked stacks. This window is owned
+ * by the system process.
+ * @hide
+ */
+ public static final int TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34;
+
+ /**
* End of types of system windows.
*/
public static final int LAST_SYSTEM_WINDOW = 2999;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 6883db2..68855ff 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -385,17 +385,19 @@
}
@Override
- void onProgressRefresh(float scale, boolean fromUser, int progress) {
- super.onProgressRefresh(scale, fromUser, progress);
+ void onVisualProgressChanged(int id, float scale) {
+ super.onVisualProgressChanged(id, scale);
- final Drawable thumb = mThumb;
- if (thumb != null) {
- setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
+ if (id == R.id.progress) {
+ final Drawable thumb = mThumb;
+ if (thumb != null) {
+ setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
- // Since we draw translated, the drawable's bounds that it signals
- // for invalidation won't be the actual bounds we want invalidated,
- // so just invalidate this whole view.
- invalidate();
+ // Since we draw translated, the drawable's bounds that it signals
+ // for invalidation won't be the actual bounds we want invalidated,
+ // so just invalidate this whole view.
+ invalidate();
+ }
}
}
@@ -709,8 +711,7 @@
case KeyEvent.KEYCODE_DPAD_RIGHT:
increment = isLayoutRtl() ? -increment : increment;
- // Let progress bar handle clamping values.
- if (setProgress(getProgress() + increment, true)) {
+ if (setProgressInternal(getProgress() + increment, true, true)) {
onKeyChange();
return true;
}
@@ -764,7 +765,7 @@
}
float value = arguments.getFloat(
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE);
- return setProgress((int) value, true);
+ return setProgressInternal((int) value, true, true);
}
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
@@ -777,7 +778,7 @@
}
// Let progress bar handle clamping values.
- if (setProgress(getProgress() + increment, true)) {
+ if (setProgressInternal(getProgress() + increment, true, true)) {
onKeyChange();
return true;
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index fce3754..04c68ae 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -16,10 +16,13 @@
package android.widget;
+import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.PorterDuff;
+import android.util.FloatProperty;
+import android.util.IntProperty;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.R;
@@ -28,7 +31,6 @@
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Shader;
@@ -38,7 +40,6 @@
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
@@ -57,6 +58,7 @@
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.Transformation;
@@ -198,9 +200,17 @@
*/
@RemoteView
public class ProgressBar extends View {
+
private static final int MAX_LEVEL = 10000;
private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
+ /** Interpolator used for smooth progress animations. */
+ private static final DecelerateInterpolator PROGRESS_ANIM_INTERPOLATOR =
+ new DecelerateInterpolator();
+
+ /** Duration of smooth progress animations. */
+ private static final int PROGRESS_ANIM_DURATION = 80;
+
int mMinWidth;
int mMaxWidth;
int mMinHeight;
@@ -234,6 +244,9 @@
private boolean mAttached;
private boolean mRefreshIsPosted;
+ /** Value used to track progress animation, in the range [0...1]. */
+ private float mVisualProgress;
+
boolean mMirrorForRtl = false;
private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
@@ -814,8 +827,8 @@
updateDrawableBounds(getWidth(), getHeight());
updateDrawableState();
- doRefreshProgress(R.id.progress, mProgress, false, false);
- doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
+ doRefreshProgress(R.id.progress, mProgress, false, false, false);
+ doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false, false);
}
}
@@ -1246,7 +1259,7 @@
final int count = mRefreshData.size();
for (int i = 0; i < count; i++) {
final RefreshData rd = mRefreshData.get(i);
- doRefreshProgress(rd.id, rd.progress, rd.fromUser, true);
+ doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
rd.recycle();
}
mRefreshData.clear();
@@ -1263,8 +1276,9 @@
public int id;
public int progress;
public boolean fromUser;
+ public boolean animate;
- public static RefreshData obtain(int id, int progress, boolean fromUser) {
+ public static RefreshData obtain(int id, int progress, boolean fromUser, boolean animate) {
RefreshData rd = sPool.acquire();
if (rd == null) {
rd = new RefreshData();
@@ -1272,6 +1286,7 @@
rd.id = id;
rd.progress = progress;
rd.fromUser = fromUser;
+ rd.animate = animate;
return rd;
}
@@ -1281,26 +1296,21 @@
}
private synchronized void doRefreshProgress(int id, int progress, boolean fromUser,
- boolean callBackToApp) {
- float scale = mMax > 0 ? (float) progress / (float) mMax : 0;
- final Drawable d = mCurrentDrawable;
- if (d != null) {
- Drawable progressDrawable = null;
+ boolean callBackToApp, boolean animate) {
+ final float scale = mMax > 0 ? progress / (float) mMax : 0;
+ final boolean isPrimary = id == R.id.progress;
- if (d instanceof LayerDrawable) {
- progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
- if (progressDrawable != null && canResolveLayoutDirection()) {
- progressDrawable.setLayoutDirection(getLayoutDirection());
- }
- }
-
- final int level = (int) (scale * MAX_LEVEL);
- (progressDrawable != null ? progressDrawable : d).setLevel(level);
+ if (isPrimary && animate) {
+ final ObjectAnimator animator = ObjectAnimator.ofFloat(this, VISUAL_PROGRESS, scale);
+ animator.setAutoCancel(true);
+ animator.setDuration(PROGRESS_ANIM_DURATION);
+ animator.setInterpolator(PROGRESS_ANIM_INTERPOLATOR);
+ animator.start();
} else {
- invalidate();
+ setVisualProgress(id, scale);
}
- if (callBackToApp && id == R.id.progress) {
+ if (isPrimary && callBackToApp) {
onProgressRefresh(scale, fromUser, progress);
}
}
@@ -1311,15 +1321,51 @@
}
}
- private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
+ /**
+ * Sets the visual state of a progress indicator.
+ *
+ * @param id the identifier of the progress indicator
+ * @param progress the visual progress in the range [0...1]
+ */
+ private void setVisualProgress(int id, float progress) {
+ mVisualProgress = progress;
+
+ Drawable d = mCurrentDrawable;
+
+ if (d instanceof LayerDrawable) {
+ d = ((LayerDrawable) d).findDrawableByLayerId(id);
+ }
+
+ if (d != null) {
+ final int level = (int) (progress * MAX_LEVEL);
+ d.setLevel(level);
+ } else {
+ invalidate();
+ }
+
+ onVisualProgressChanged(id, progress);
+ }
+
+ /**
+ * Called when the visual state of a progress indicator changes.
+ *
+ * @param id the identifier of the progress indicator
+ * @param progress the visual progress in the range [0...1]
+ */
+ void onVisualProgressChanged(int id, float progress) {
+ // Stub method.
+ }
+
+ private synchronized void refreshProgress(int id, int progress, boolean fromUser,
+ boolean animate) {
if (mUiThreadId == Thread.currentThread().getId()) {
- doRefreshProgress(id, progress, fromUser, true);
+ doRefreshProgress(id, progress, fromUser, true, animate);
} else {
if (mRefreshProgressRunnable == null) {
mRefreshProgressRunnable = new RefreshProgressRunnable();
}
- final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
+ final RefreshData rd = RefreshData.obtain(id, progress, fromUser, animate);
mRefreshData.add(rd);
if (mAttached && !mRefreshIsPosted) {
post(mRefreshProgressRunnable);
@@ -1329,8 +1375,8 @@
}
/**
- * <p>Set the current progress to the specified value. Does not do anything
- * if the progress bar is in indeterminate mode.</p>
+ * Sets the current progress to the specified value. Does not do anything
+ * if the progress bar is in indeterminate mode.
*
* @param progress the new progress, between 0 and {@link #getMax()}
*
@@ -1341,11 +1387,26 @@
*/
@android.view.RemotableViewMethod
public synchronized void setProgress(int progress) {
- setProgress(progress, false);
+ setProgressInternal(progress, false, false);
+ }
+
+ /**
+ * Sets the current progress to the specified value, optionally animating
+ * between the current and target values.
+ * <p>
+ * Animation does not affect the result of {@link #getProgress()}, which
+ * will return the target value immediately after this method is called.
+ *
+ * @param progress the new progress value, between 0 and {@link #getMax()}
+ * @param animate {@code true} to animate between the current and target
+ * values or {@code false} to not animate
+ */
+ public void setProgress(int progress, boolean animate) {
+ setProgressInternal(progress, false, animate);
}
@android.view.RemotableViewMethod
- synchronized boolean setProgress(int progress, boolean fromUser) {
+ synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
if (mIndeterminate) {
// Not applicable.
return false;
@@ -1359,7 +1420,7 @@
}
mProgress = progress;
- refreshProgress(R.id.progress, mProgress, fromUser);
+ refreshProgress(R.id.progress, mProgress, fromUser, animate);
return true;
}
@@ -1391,7 +1452,7 @@
if (secondaryProgress != mSecondaryProgress) {
mSecondaryProgress = secondaryProgress;
- refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false);
+ refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
}
}
@@ -1464,7 +1525,7 @@
if (mProgress > max) {
mProgress = max;
}
- refreshProgress(R.id.progress, mProgress, false);
+ refreshProgress(R.id.progress, mProgress, false, false);
}
}
@@ -1847,7 +1908,7 @@
final int count = mRefreshData.size();
for (int i = 0; i < count; i++) {
final RefreshData rd = mRefreshData.get(i);
- doRefreshProgress(rd.id, rd.progress, rd.fromUser, true);
+ doRefreshProgress(rd.id, rd.progress, rd.fromUser, true, rd.animate);
rd.recycle();
}
mRefreshData.clear();
@@ -1956,4 +2017,23 @@
boolean mHasSecondaryProgressTint;
boolean mHasSecondaryProgressTintMode;
}
+
+ /**
+ * Property wrapper around the visual state of the {@code progress} functionality
+ * handled by the {@link ProgressBar#setProgress(int, boolean)} method. This does
+ * not correspond directly to the actual progress -- only the visual state.
+ */
+ private final FloatProperty<ProgressBar> VISUAL_PROGRESS =
+ new FloatProperty<ProgressBar>("visual_progress") {
+ @Override
+ public void setValue(ProgressBar object, float value) {
+ object.setVisualProgress(R.id.progress, value);
+ object.mVisualProgress = value;
+ }
+
+ @Override
+ public Float get(ProgressBar object) {
+ return object.mVisualProgress;
+ }
+ };
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 6f3a711..434516d 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1387,7 +1387,7 @@
mTrackDrawable.jumpToCurrentState();
}
- if (mPositionAnimator != null && mPositionAnimator.isRunning()) {
+ if (mPositionAnimator != null && mPositionAnimator.isStarted()) {
mPositionAnimator.end();
mPositionAnimator = null;
}
diff --git a/core/res/res/layout/docked_stack_divider.xml b/core/res/res/layout/docked_stack_divider.xml
new file mode 100644
index 0000000..aa6e68d
--- /dev/null
+++ b/core/res/res/layout/docked_stack_divider.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/docked_stack_divider_thickness"
+ android:layout_height="match_parent"
+ android:background="@android:color/black"
+ />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 902d40d..dc96df4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5550,6 +5550,8 @@
<!-- Push object to the end of its container, not changing its size. -->
<flag name="end" value="0x00800005" />
</attr>
+ <!-- Specifies the initial drawable level in the range 0 to 10000. -->
+ <attr name="level" format="integer" />
<!-- Reference to a drawable resource to draw with the specified scale. -->
<attr name="drawable" />
<!-- Use the drawable's intrinsic width and height as minimum size values.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a19bc20..9b1a613 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -410,6 +410,9 @@
radio is unable to find any MCC information to infer wifi country code from -->
<bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
+ <!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
+ <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">false</bool>
+
<!-- Integer specifying the basic autojoin parameters -->
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_factor">5</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8635a4f..2621bc9c 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -45,6 +45,9 @@
<!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
<dimen name="status_bar_edge_ignore">5dp</dimen>
+ <!-- Width of a divider bar used to resize docked stacks. -->
+ <dimen name="docked_stack_divider_thickness">24dp</dimen>
+
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b6284c9..89d9bab 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2673,6 +2673,7 @@
<public type="attr" name="maxButtonHeight" />
<public type="attr" name="buttonGravity" />
<public type="attr" name="collapseIcon" />
+ <public type="attr" name="level" />
<public type="style" name="Theme.Material.DayNight" />
<public type="style" name="Theme.Material.DayNight.DarkActionBar" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4edc847..b5efbfd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -307,6 +307,7 @@
<java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
<java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
+ <java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
<java-symbol type="bool" name="config_supportMicNearUltrasound" />
<java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
<java-symbol type="integer" name="config_wifi_framework_5GHz_preference_boost_threshold" />
@@ -1477,6 +1478,7 @@
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="config_supportAutoRotation" />
<java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
+ <java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="navigation_bar_height" />
<java-symbol type="dimen" name="navigation_bar_height_landscape" />
<java-symbol type="dimen" name="navigation_bar_width" />
@@ -1719,6 +1721,7 @@
<java-symbol type="integer" name="config_undockedHdmiRotation" />
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
<java-symbol type="layout" name="am_compat_mode_dialog" />
+ <java-symbol type="layout" name="docked_stack_divider" />
<java-symbol type="layout" name="launch_warning" />
<java-symbol type="layout" name="safe_mode" />
<java-symbol type="layout" name="simple_list_item_2_single_choice" />
diff --git a/docs/html/training/location/geofencing.jd b/docs/html/training/location/geofencing.jd
index 59fc4c6..556329c 100644
--- a/docs/html/training/location/geofencing.jd
+++ b/docs/html/training/location/geofencing.jd
@@ -100,8 +100,8 @@
<h3>Create geofence objects</h3>
<p>
- First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.
- html">Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
+ First, use <code><a href="{@docRoot}reference/com/google/android/gms/location/Geofence.Builder.html">
+ Geofence.Builder</a></code> to create a geofence, setting the desired radius, duration, and
transition types for the geofence. For example, to populate a list object named
{@code mGeofenceList}:
</p>
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 0acbeda..f9206b7 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -35,19 +35,29 @@
/**
* A Drawable that changes the size of another Drawable based on its current
- * level value. You can control how much the child Drawable changes in width
+ * level value. You can control how much the child Drawable changes in width
* and height based on the level, as well as a gravity to control where it is
- * placed in its overall container. Most often used to implement things like
+ * placed in its overall container. Most often used to implement things like
* progress bars.
- *
- * <p>It can be defined in an XML file with the <code><scale></code> element. For more
- * information, see the guide to <a
- * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ * <p>
+ * The default level may be specified from XML using the
+ * {@link android.R.styleable#ScaleDrawable_level android:level} property. When
+ * this property is not specified, the default level is 0, which corresponds to
+ * zero height and/or width depending on the values specified for
+ * {@code android.R.styleable#ScaleDrawable_scaleWidth scaleWidth} and
+ * {@code android.R.styleable#ScaleDrawable_scaleHeight scaleHeight}. At run
+ * time, the level may be set via {@link #setLevel(int)}.
+ * <p>
+ * A scale drawable may be defined in an XML file with the {@code <scale>}
+ * element. For more information, see the guide to
+ * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable
+ * Resources</a>.
*
* @attr ref android.R.styleable#ScaleDrawable_scaleWidth
* @attr ref android.R.styleable#ScaleDrawable_scaleHeight
* @attr ref android.R.styleable#ScaleDrawable_scaleGravity
* @attr ref android.R.styleable#ScaleDrawable_drawable
+ * @attr ref android.R.styleable#ScaleDrawable_level
*/
public class ScaleDrawable extends DrawableWrapper {
private static final int MAX_LEVEL = 10000;
@@ -92,6 +102,8 @@
inflateChildDrawable(r, parser, attrs, theme);
verifyRequiredAttributes(a);
a.recycle();
+
+ updateLocalState();
}
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
@@ -117,6 +129,8 @@
R.styleable.ScaleDrawable_scaleGravity, state.mGravity);
state.mUseIntrinsicSizeAsMin = a.getBoolean(
R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, state.mUseIntrinsicSizeAsMin);
+ state.mInitialLevel = a.getInt(
+ R.styleable.ScaleDrawable_level, state.mInitialLevel);
final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
if (dr != null) {
@@ -165,6 +179,8 @@
// The drawable may have changed as a result of applying the theme, so
// apply the theme to the wrapped drawable last.
super.applyTheme(t);
+
+ updateLocalState();
}
@Override
@@ -239,6 +255,7 @@
float mScaleHeight = DO_NOT_SCALE;
int mGravity = Gravity.LEFT;
boolean mUseIntrinsicSizeAsMin = false;
+ int mInitialLevel = 0;
ScaleState(ScaleState orig) {
super(orig);
@@ -248,6 +265,7 @@
mScaleHeight = orig.mScaleHeight;
mGravity = orig.mGravity;
mUseIntrinsicSizeAsMin = orig.mUseIntrinsicSizeAsMin;
+ mInitialLevel = orig.mInitialLevel;
}
}
@@ -257,10 +275,23 @@
}
}
+ /**
+ * Creates a new ScaleDrawable based on the specified constant state.
+ * <p>
+ * The resulting drawable is guaranteed to have a new constant state.
+ *
+ * @param state constant state from which the drawable inherits
+ */
private ScaleDrawable(ScaleState state, Resources res) {
super(state, res);
mState = state;
+
+ updateLocalState();
+ }
+
+ private void updateLocalState() {
+ setLevel(mState.mInitialLevel);
}
}
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index ff71313..7c63e31 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -54,7 +54,6 @@
, mInitialized(false) {
INIT_LOGD("Creating OpenGL renderer caches");
init();
- initFont();
initConstraints();
initStaticProperties();
initExtensions();
@@ -78,10 +77,6 @@
return true;
}
-void Caches::initFont() {
- fontRenderer = GammaFontRenderer::createRenderer();
-}
-
void Caches::initExtensions() {
if (mExtensions.hasDebugMarker()) {
eventMark = glInsertEventMarkerEXT;
@@ -100,15 +95,9 @@
}
void Caches::initStaticProperties() {
- gpuPixelBuffersEnabled = false;
-
// OpenGL ES 3.0+ specific features
- if (mExtensions.hasPixelBufferObjects()) {
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, property, "true") > 0) {
- gpuPixelBuffersEnabled = !strcmp(property, "true");
- }
- }
+ gpuPixelBuffersEnabled = mExtensions.hasPixelBufferObjects()
+ && property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
}
void Caches::terminate() {
@@ -203,14 +192,14 @@
dropShadowCache.getMaxSize());
log.appendFormat(" PatchCache %8d / %8d\n",
patchCache.getSize(), patchCache.getMaxSize());
- for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
- const uint32_t sizeA8 = fontRenderer->getFontRendererSize(i, GL_ALPHA);
- const uint32_t sizeRGBA = fontRenderer->getFontRendererSize(i, GL_RGBA);
- log.appendFormat(" FontRenderer %d A8 %8d / %8d\n", i, sizeA8, sizeA8);
- log.appendFormat(" FontRenderer %d RGBA %8d / %8d\n", i, sizeRGBA, sizeRGBA);
- log.appendFormat(" FontRenderer %d total %8d / %8d\n", i, sizeA8 + sizeRGBA,
- sizeA8 + sizeRGBA);
- }
+
+ const uint32_t sizeA8 = fontRenderer.getFontRendererSize(GL_ALPHA);
+ const uint32_t sizeRGBA = fontRenderer.getFontRendererSize(GL_RGBA);
+ log.appendFormat(" FontRenderer A8 %8d / %8d\n", sizeA8, sizeA8);
+ log.appendFormat(" FontRenderer RGBA %8d / %8d\n", sizeRGBA, sizeRGBA);
+ log.appendFormat(" FontRenderer total %8d / %8d\n", sizeA8 + sizeRGBA,
+ sizeA8 + sizeRGBA);
+
log.appendFormat("Other:\n");
log.appendFormat(" FboCache %8d / %8d\n",
fboCache.getSize(), fboCache.getMaxSize());
@@ -222,10 +211,8 @@
total += tessellationCache.getSize();
total += dropShadowCache.getSize();
total += patchCache.getSize();
- for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
- total += fontRenderer->getFontRendererSize(i, GL_ALPHA);
- total += fontRenderer->getFontRendererSize(i, GL_RGBA);
- }
+ total += fontRenderer.getFontRendererSize(GL_ALPHA);
+ total += fontRenderer.getFontRendererSize(GL_RGBA);
log.appendFormat("Total memory usage:\n");
log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
@@ -250,12 +237,12 @@
patchCache.clear();
dropShadowCache.clear();
gradientCache.clear();
- fontRenderer->clear();
+ fontRenderer.clear();
fboCache.clear();
dither.clear();
// fall through
case FlushMode::Moderate:
- fontRenderer->flush();
+ fontRenderer.flush();
textureCache.flush();
pathCache.clear();
tessellationCache.clear();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 929db17..61e958d 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -21,6 +21,7 @@
#include "Dither.h"
#include "Extensions.h"
#include "FboCache.h"
+#include "GammaFontRenderer.h"
#include "GradientCache.h"
#include "LayerCache.h"
#include "PatchCache.h"
@@ -53,8 +54,6 @@
namespace android {
namespace uirenderer {
-class GammaFontRenderer;
-
///////////////////////////////////////////////////////////////////////////////
// Caches
///////////////////////////////////////////////////////////////////////////////
@@ -156,7 +155,7 @@
TextDropShadowCache dropShadowCache;
FboCache fboCache;
- GammaFontRenderer* fontRenderer;
+ GammaFontRenderer fontRenderer;
TaskManager tasks;
@@ -178,8 +177,6 @@
TextureState& textureState() { return *mTextureState; }
private:
-
- void initFont();
void initExtensions();
void initConstraints();
void initStaticProperties();
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 9fb1e75..a81ffb9 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -631,7 +631,7 @@
void DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
ATRACE_NAME("flush drawing commands");
- Caches::getInstance().fontRenderer->endPrecaching();
+ Caches::getInstance().fontRenderer.endPrecaching();
if (isEmpty()) return; // nothing to flush
renderer.restoreToCount(1);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 14126a9..dc5cb8b 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1246,7 +1246,7 @@
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
+ FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
@@ -1311,7 +1311,7 @@
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
const DeferredDisplayState& state) override {
- FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
+ FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
SkMatrix transform;
renderer.findBestFontTransform(state.mMatrix, &transform);
if (mPrecacheTransform != transform) {
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 75c3ead..4b9d4f9 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -75,8 +75,8 @@
static bool sLogFontRendererCreate = true;
-FontRenderer::FontRenderer()
- : mGammaTable(nullptr)
+FontRenderer::FontRenderer(const uint8_t* gammaTable)
+ : mGammaTable(gammaTable)
, mCurrentFont(nullptr)
, mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity)
, mCurrentCacheTexture(nullptr)
@@ -92,27 +92,15 @@
INIT_LOGD("Creating FontRenderer");
}
- mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH;
- mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT;
- mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH;
- mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT;
+ mSmallCacheWidth = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_WIDTH,
+ DEFAULT_TEXT_SMALL_CACHE_WIDTH);
+ mSmallCacheHeight = property_get_int32(PROPERTY_TEXT_SMALL_CACHE_HEIGHT,
+ DEFAULT_TEXT_SMALL_CACHE_HEIGHT);
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, nullptr) > 0) {
- mSmallCacheWidth = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, nullptr) > 0) {
- mSmallCacheHeight = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, nullptr) > 0) {
- mLargeCacheWidth = atoi(property);
- }
-
- if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, nullptr) > 0) {
- mLargeCacheHeight = atoi(property);
- }
+ mLargeCacheWidth = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_WIDTH,
+ DEFAULT_TEXT_LARGE_CACHE_WIDTH);
+ mLargeCacheHeight = property_get_int32(PROPERTY_TEXT_LARGE_CACHE_HEIGHT,
+ DEFAULT_TEXT_LARGE_CACHE_HEIGHT);
uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize;
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 2954975..936c838 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -72,16 +72,12 @@
class FontRenderer {
public:
- FontRenderer();
+ FontRenderer(const uint8_t* gammaTable);
~FontRenderer();
void flushLargeCaches(std::vector<CacheTexture*>& cacheTextures);
void flushLargeCaches();
- void setGammaTable(const uint8_t* gammaTable) {
- mGammaTable = gammaTable;
- }
-
void setFont(const SkPaint* paint, const SkMatrix& matrix);
void precache(const SkPaint* paint, const char* text, int numGlyphs, const SkMatrix& matrix);
diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp
index 6c3d04e..96cac86 100644
--- a/libs/hwui/GammaFontRenderer.cpp
+++ b/libs/hwui/GammaFontRenderer.cpp
@@ -21,183 +21,22 @@
namespace android {
namespace uirenderer {
-///////////////////////////////////////////////////////////////////////////////
-// Utils
-///////////////////////////////////////////////////////////////////////////////
-
-static int luminance(const SkPaint* paint) {
- uint32_t c = paint->getColor();
- const int r = (c >> 16) & 0xFF;
- const int g = (c >> 8) & 0xFF;
- const int b = (c ) & 0xFF;
- return (r * 2 + g * 5 + b) >> 3;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Base class GammaFontRenderer
-///////////////////////////////////////////////////////////////////////////////
-
-GammaFontRenderer* GammaFontRenderer::createRenderer() {
- // Choose the best renderer
- char property[PROPERTY_VALUE_MAX];
- if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) {
- if (!strcasecmp(property, "lookup")) {
- return new LookupGammaFontRenderer();
- }
- }
-
- return new Lookup3GammaFontRenderer();
-}
-
GammaFontRenderer::GammaFontRenderer() {
- // Get the renderer properties
- char property[PROPERTY_VALUE_MAX];
-
- // Get the gamma
- mGamma = DEFAULT_TEXT_GAMMA;
- if (property_get(PROPERTY_TEXT_GAMMA, property, nullptr) > 0) {
- INIT_LOGD(" Setting text gamma to %s", property);
- mGamma = atof(property);
- } else {
- INIT_LOGD(" Using default text gamma of %.2f", DEFAULT_TEXT_GAMMA);
- }
-
- // Get the black gamma threshold
- mBlackThreshold = DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD;
- if (property_get(PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD, property, nullptr) > 0) {
- INIT_LOGD(" Setting text black gamma threshold to %s", property);
- mBlackThreshold = atoi(property);
- } else {
- INIT_LOGD(" Using default text black gamma threshold of %d",
- DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD);
- }
-
- // Get the white gamma threshold
- mWhiteThreshold = DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD;
- if (property_get(PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD, property, nullptr) > 0) {
- INIT_LOGD(" Setting text white gamma threshold to %s", property);
- mWhiteThreshold = atoi(property);
- } else {
- INIT_LOGD(" Using default white black gamma threshold of %d",
- DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD);
- }
-}
-
-GammaFontRenderer::~GammaFontRenderer() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Lookup-based renderer
-///////////////////////////////////////////////////////////////////////////////
-
-LookupGammaFontRenderer::LookupGammaFontRenderer()
- : GammaFontRenderer() {
INIT_LOGD("Creating lookup gamma font renderer");
// Compute the gamma tables
- const float gamma = 1.0f / mGamma;
+ const float gamma = 1.0f / Properties::textGamma;
for (uint32_t i = 0; i <= 255; i++) {
mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f));
}
-
- mRenderer = nullptr;
}
-void LookupGammaFontRenderer::endPrecaching() {
+void GammaFontRenderer::endPrecaching() {
if (mRenderer) {
mRenderer->endPrecaching();
}
}
-///////////////////////////////////////////////////////////////////////////////
-// Lookup-based renderer, using 3 different correction tables
-///////////////////////////////////////////////////////////////////////////////
-
-Lookup3GammaFontRenderer::Lookup3GammaFontRenderer()
- : GammaFontRenderer() {
- INIT_LOGD("Creating lookup3 gamma font renderer");
-
- // Compute the gamma tables
- const float blackGamma = mGamma;
- const float whiteGamma = 1.0f / mGamma;
-
- for (uint32_t i = 0; i <= 255; i++) {
- const float v = i / 255.0f;
- const float black = pow(v, blackGamma);
- const float white = pow(v, whiteGamma);
-
- mGammaTable[i] = i;
- mGammaTable[256 + i] = uint8_t((float)::floor(black * 255.0f + 0.5f));
- mGammaTable[512 + i] = uint8_t((float)::floor(white * 255.0f + 0.5f));
- }
-
- memset(mRenderers, 0, sizeof(FontRenderer*) * kGammaCount);
- memset(mRenderersUsageCount, 0, sizeof(uint32_t) * kGammaCount);
-}
-
-void Lookup3GammaFontRenderer::endPrecaching() {
- for (int i = 0; i < kGammaCount; i++) {
- if (mRenderers[i]) {
- mRenderers[i]->endPrecaching();
- }
- }
-}
-
-void Lookup3GammaFontRenderer::clear() {
- for (int i = 0; i < kGammaCount; i++) {
- mRenderers[i].release();
- }
-}
-
-void Lookup3GammaFontRenderer::flush() {
- int count = 0;
- int min = -1;
- uint32_t minCount = UINT_MAX;
-
- for (int i = 0; i < kGammaCount; i++) {
- if (mRenderers[i]) {
- count++;
- if (mRenderersUsageCount[i] < minCount) {
- minCount = mRenderersUsageCount[i];
- min = i;
- }
- }
- }
-
- if (count <= 1 || min < 0) return;
-
- mRenderers[min].release();
-
- // Also eliminate the caches for large glyphs, as they consume significant memory
- for (int i = 0; i < kGammaCount; ++i) {
- if (mRenderers[i]) {
- mRenderers[i]->flushLargeCaches();
- }
- }
-}
-
-FontRenderer* Lookup3GammaFontRenderer::getRenderer(Gamma gamma) {
- if (!mRenderers[gamma]) {
- mRenderers[gamma].reset(new FontRenderer());
- mRenderers[gamma]->setGammaTable(&mGammaTable[gamma * 256]);
- }
- mRenderersUsageCount[gamma]++;
- return mRenderers[gamma].get();
-}
-
-FontRenderer& Lookup3GammaFontRenderer::getFontRenderer(const SkPaint* paint) {
- if (paint->getShader() == nullptr) {
- const int l = luminance(paint);
-
- if (l <= mBlackThreshold) {
- return *getRenderer(kGammaBlack);
- } else if (l >= mWhiteThreshold) {
- return *getRenderer(kGammaWhite);
- }
- }
- return *getRenderer(kGammaDefault);
-}
-
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 03f2510..146d385 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -17,122 +17,44 @@
#ifndef ANDROID_HWUI_GAMMA_FONT_RENDERER_H
#define ANDROID_HWUI_GAMMA_FONT_RENDERER_H
-#include <SkPaint.h>
-
#include "FontRenderer.h"
#include "Program.h"
+#include <SkPaint.h>
+
namespace android {
namespace uirenderer {
class GammaFontRenderer {
public:
- virtual ~GammaFontRenderer();
-
- virtual void clear() = 0;
- virtual void flush() = 0;
-
- virtual FontRenderer& getFontRenderer(const SkPaint* paint) = 0;
-
- virtual uint32_t getFontRendererCount() const = 0;
- virtual uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const = 0;
-
- virtual void endPrecaching() = 0;
-
- static GammaFontRenderer* createRenderer();
-
-protected:
GammaFontRenderer();
- int mBlackThreshold;
- int mWhiteThreshold;
-
- float mGamma;
-};
-
-class LookupGammaFontRenderer: public GammaFontRenderer {
-public:
- ~LookupGammaFontRenderer() {
- delete mRenderer;
+ void clear() {
+ mRenderer.release();
}
- void clear() override {
- delete mRenderer;
- mRenderer = nullptr;
- }
-
- void flush() override {
+ void flush() {
if (mRenderer) {
mRenderer->flushLargeCaches();
}
}
- FontRenderer& getFontRenderer(const SkPaint* paint) override {
+ FontRenderer& getFontRenderer() {
if (!mRenderer) {
- mRenderer = new FontRenderer;
- mRenderer->setGammaTable(&mGammaTable[0]);
+ mRenderer.reset(new FontRenderer(&mGammaTable[0]));
}
return *mRenderer;
}
- uint32_t getFontRendererCount() const override {
- return 1;
- }
-
- uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override {
+ uint32_t getFontRendererSize(GLenum format) const {
return mRenderer ? mRenderer->getCacheSize(format) : 0;
}
- void endPrecaching() override;
+ void endPrecaching();
private:
- LookupGammaFontRenderer();
-
- FontRenderer* mRenderer;
+ std::unique_ptr<FontRenderer> mRenderer;
uint8_t mGammaTable[256];
-
- friend class GammaFontRenderer;
-};
-
-class Lookup3GammaFontRenderer: public GammaFontRenderer {
-public:
- void clear() override;
- void flush() override;
-
- FontRenderer& getFontRenderer(const SkPaint* paint) override;
-
- uint32_t getFontRendererCount() const override {
- return kGammaCount;
- }
-
- uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override {
- if (fontRenderer >= kGammaCount) return 0;
-
- if (!mRenderers[fontRenderer]) return 0;
-
- return mRenderers[fontRenderer]->getCacheSize(format);
- }
-
- void endPrecaching() override;
-
-private:
- Lookup3GammaFontRenderer();
-
- enum Gamma {
- kGammaDefault = 0,
- kGammaBlack = 1,
- kGammaWhite = 2,
- kGammaCount = 3
- };
-
- FontRenderer* getRenderer(Gamma gamma);
-
- uint32_t mRenderersUsageCount[kGammaCount];
- std::unique_ptr<FontRenderer> mRenderers[kGammaCount];
-
- uint8_t mGammaTable[256 * kGammaCount];
-
- friend class GammaFontRenderer;
};
}; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e06e348..a401ce1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2014,7 +2014,7 @@
y = floorf(y + currentTransform()->getTranslateY() + 0.5f);
}
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
fontRenderer.setFont(paint, SkMatrix::I());
int alpha;
@@ -2166,7 +2166,7 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
if (CC_UNLIKELY(hasTextShadow(paint))) {
fontRenderer.setFont(paint, SkMatrix::I());
@@ -2234,7 +2234,7 @@
// TODO: avoid scissor by calculating maximum bounds using path bounds + font metrics
mRenderState.scissor().setEnabled(true);
- FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
fontRenderer.setFont(paint, SkMatrix::I());
fontRenderer.setTextureFiltering(true);
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index b8f8585..36a8dac 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -33,6 +33,8 @@
bool Properties::useBufferAge = true;
bool Properties::enablePartialUpdates = true;
+float Properties::textGamma = DEFAULT_TEXT_GAMMA;
+
DebugLevel Properties::debugLevel = kDebugDisabled;
OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default;
StencilClipDebug Properties::debugStencilClip = StencilClipDebug::Hide;
@@ -47,6 +49,15 @@
ProfileType Properties::sProfileType = ProfileType::None;
bool Properties::sDisableProfileBars = false;
+static float property_get_float(const char* key, float defaultValue) {
+ char buf[PROPERTY_VALUE_MAX] = {'\0',};
+
+ if (property_get(PROPERTY_PROFILE, buf, "") > 0) {
+ return atof(buf);
+ }
+ return defaultValue;
+}
+
bool Properties::load() {
char property[PROPERTY_VALUE_MAX];
bool prevDebugLayersUpdates = debugLayersUpdates;
@@ -110,6 +121,8 @@
useBufferAge = property_get_bool(PROPERTY_USE_BUFFER_AGE, true);
enablePartialUpdates = property_get_bool(PROPERTY_ENABLE_PARTIAL_UPDATES, true);
+ textGamma = property_get_float(PROPERTY_TEXT_GAMMA, DEFAULT_TEXT_GAMMA);
+
return (prevDebugLayersUpdates != debugLayersUpdates)
|| (prevDebugOverdraw != debugOverdraw)
|| (prevDebugStencilClip != debugStencilClip);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 98834b8..3512c36 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -208,30 +208,8 @@
#define PROPERTY_TEXT_LARGE_CACHE_WIDTH "ro.hwui.text_large_cache_width"
#define PROPERTY_TEXT_LARGE_CACHE_HEIGHT "ro.hwui.text_large_cache_height"
-// Indicates whether gamma correction should be applied in the shaders
-// or in lookup tables. Accepted values:
-//
-// - "lookup3", correction based on lookup tables. Gamma correction
-// is different for black and white text (see thresholds below)
-//
-// - "lookup", correction based on a single lookup table
-//
-// - "shader3", correction applied by a GLSL shader. Gamma correction
-// is different for black and white text (see thresholds below)
-//
-// - "shader", correction applied by a GLSL shader
-//
-// See PROPERTY_TEXT_GAMMA, PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD and
-// PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD for more control.
-#define PROPERTY_TEXT_GAMMA_METHOD "hwui.text_gamma_correction"
-#define DEFAULT_TEXT_GAMMA_METHOD "lookup"
-
// Gamma (>= 1.0, <= 10.0)
#define PROPERTY_TEXT_GAMMA "hwui.text_gamma"
-// Luminance threshold below which black gamma correction is applied. Range: [0..255]
-#define PROPERTY_TEXT_BLACK_GAMMA_THRESHOLD "hwui.text_gamma.black_threshold"
-// Lumincance threshold above which white gamma correction is applied. Range: [0..255]
-#define PROPERTY_TEXT_WHITE_GAMMA_THRESHOLD "hwui.text_gamma.white_threshold"
///////////////////////////////////////////////////////////////////////////////
// Default property values
@@ -250,8 +228,6 @@
#define DEFAULT_TEXTURE_CACHE_FLUSH_RATE 0.6f
#define DEFAULT_TEXT_GAMMA 1.4f
-#define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
-#define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192
///////////////////////////////////////////////////////////////////////////////
// Misc
@@ -300,6 +276,8 @@
static bool useBufferAge;
static bool enablePartialUpdates;
+ static float textGamma;
+
static DebugLevel debugLevel;
static OverdrawColorSet overdrawColorSet;
static StencilClipDebug debugStencilClip;
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0fe5509..abb464e 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -76,8 +76,9 @@
String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
if (server == null) server = DEFAULT_SERVER;
mCm = ConnectivityManager.from(this);
+ String url = getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
try {
- mURL = new URL("http", server, "/generate_204");
+ mURL = url != null ? new URL(url) : new URL("http", server, "/generate_204");
} catch (MalformedURLException e) {
// System misconfigured, bail out in a way that at least provides network access.
Log.e(TAG, "Invalid captive portal URL, server=" + server);
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 97bc8fd..ac6f950 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -35,11 +35,6 @@
<action android:name="android.intent.action.OPEN_DOCUMENT_TREE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- <intent-filter>
- <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.document/root" />
- </intent-filter>
</activity>
<activity
@@ -63,6 +58,11 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.document/root" />
+ </intent-filter>
</activity>
<provider
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 4d0a7eb..1585908 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -16,13 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
-import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
-import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_COPY_DESTINATION;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
@@ -125,22 +118,6 @@
}
@Override
- public void onResume() {
- super.onResume();
-
- final State state = getDisplayState();
- final RootInfo root = getCurrentRoot();
-
- // If we're browsing a specific root, and that root went away, then we
- // have no reason to hang around
- if (state.action == State.ACTION_BROWSE && root != null) {
- if (mRoots.getRootBlocking(root.authority, root.rootId) == null) {
- finish();
- }
- }
- }
-
- @Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean showMenu = super.onCreateOptionsMenu(menu);
@@ -178,8 +155,10 @@
State state = getDisplayState();
sortSize.setVisible(state.showSize); // Only sort by size when visible
+ fileSize.setVisible(!state.showSize);
grid.setVisible(state.derivedMode != State.MODE_GRID);
list.setVisible(state.derivedMode != State.MODE_LIST);
+ advanced.setVisible(!mState.showAdvanced);
settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
return shown;
@@ -189,13 +168,17 @@
State state = new State();
final Intent intent = getIntent();
- final String action = intent.getAction();
state.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
- state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
- state.showAdvanced = state.forceAdvanced ||
- LocalPreferences.getDisplayAdvancedDevices(this);
+ state.forceSize = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, false);
+ state.showSize = state.forceSize || LocalPreferences.getDisplayFileSize(this);
+
+ state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+ state.showAdvanced = state.forceAdvanced
+ || LocalPreferences.getDisplayAdvancedDevices(this);
+
+ state.initAcceptMimes(intent);
state.excludedAuthorities = getExcludedAuthorities();
return state;
@@ -219,7 +202,7 @@
if (mRoots.isRecentsRoot(root)) {
onCurrentDirectoryChanged(ANIM_SIDE);
} else {
- new PickRootTask(root).executeOnExecutor(getCurrentExecutor());
+ new PickRootTask(root).executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -399,6 +382,7 @@
public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
public boolean allowMultiple;
+ public boolean forceSize ;
public boolean showSize;
public boolean localOnly ;
public boolean forceAdvanced ;
@@ -429,7 +413,6 @@
public static final int ACTION_OPEN_TREE = 4;
public static final int ACTION_MANAGE = 5;
public static final int ACTION_BROWSE = 6;
- public static final int ACTION_BROWSE_ALL = 7;
public static final int ACTION_OPEN_COPY_DESTINATION = 8;
public static final int MODE_UNKNOWN = 0;
@@ -441,6 +424,15 @@
public static final int SORT_ORDER_LAST_MODIFIED = 2;
public static final int SORT_ORDER_SIZE = 3;
+ public void initAcceptMimes(Intent intent) {
+ if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
+ acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
+ } else {
+ String glob = intent.getType();
+ acceptMimes = new String[] { glob != null ? glob : "*/*" };
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -453,6 +445,7 @@
out.writeStringArray(acceptMimes);
out.writeInt(userSortOrder);
out.writeInt(allowMultiple ? 1 : 0);
+ out.writeInt(forceSize ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
out.writeInt(forceAdvanced ? 1 : 0);
@@ -475,6 +468,7 @@
state.acceptMimes = in.readStringArray();
state.userSortOrder = in.readInt();
state.allowMultiple = in.readInt() != 0;
+ state.forceSize = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
state.forceAdvanced = in.readInt() != 0;
@@ -562,7 +556,7 @@
return getDisplayState().stack.peek();
}
- public Executor getCurrentExecutor() {
+ public Executor getExecutorForCurrentDirectory() {
final DocumentInfo cwd = getCurrentDirectory();
if (cwd != null && cwd.authority != null) {
return ProviderExecutor.forAuthority(cwd.authority);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 1a17b6c..ea8ecf5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE_ALL;
import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
import static com.android.documentsui.BaseActivity.State.MODE_GRID;
@@ -101,7 +100,6 @@
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
import com.google.common.collect.Lists;
@@ -1554,9 +1552,9 @@
}
private FragmentTuner pickFragmentTuner(final State state) {
- return state.action == ACTION_BROWSE_ALL
+ return state.action == ACTION_BROWSE
? new FilesTuner()
- : new DefaultTuner(state);
+ : new DefaultTuner(state.action);
}
/**
@@ -1593,15 +1591,14 @@
*/
private static final class DefaultTuner implements FragmentTuner {
- private final State mState;
+ private final boolean mManaging;
- public DefaultTuner(State state) {
- mState = state;
+ public DefaultTuner(int action) {
+ mManaging = (action == ACTION_MANAGE);
}
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
- Preconditions.checkState(mState.action != ACTION_BROWSE_ALL);
final MenuItem open = menu.findItem(R.id.menu_open);
final MenuItem share = menu.findItem(R.id.menu_share);
@@ -1610,14 +1607,11 @@
final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
final MenuItem copyToClipboard = menu.findItem(R.id.menu_copy_to_clipboard);
- final boolean manageOrBrowse = (mState.action == ACTION_MANAGE
- || mState.action == ACTION_BROWSE);
-
- open.setVisible(!manageOrBrowse);
- share.setVisible(manageOrBrowse);
- delete.setVisible(manageOrBrowse && canDelete);
+ open.setVisible(!mManaging);
+ share.setVisible(mManaging);
+ delete.setVisible(mManaging && canDelete);
// Disable copying from the Recents view.
- copyTo.setVisible(manageOrBrowse && dirType != TYPE_RECENT_OPEN);
+ copyTo.setVisible(mManaging && dirType != TYPE_RECENT_OPEN);
moveTo.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false));
// Only shown in files mode.
@@ -1634,6 +1628,7 @@
private static final class FilesTuner implements FragmentTuner {
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
+
menu.findItem(R.id.menu_share).setVisible(true);
menu.findItem(R.id.menu_delete).setVisible(canDelete);
menu.findItem(R.id.menu_copy_to_clipboard).setVisible(true);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 8b2b4f2..dbfcf40 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,7 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
@@ -28,7 +27,6 @@
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
-import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.ContentProviderClient;
@@ -44,7 +42,6 @@
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Root;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -87,7 +84,7 @@
super.onCreate(icicle);
final Resources res = getResources();
- mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_BROWSE;
+ mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
if (!mShowAsDialog) {
setTheme(R.style.DocumentsNonDialogTheme);
@@ -123,14 +120,6 @@
setActionBar(mToolbar);
- // Hide roots when we're managing a specific root
- if (mState.action == ACTION_BROWSE) {
- mDrawer.lockClosed();
- if (mShowAsDialog) {
- findViewById(R.id.container_roots).setVisibility(View.GONE);
- }
- }
-
if (mState.action == ACTION_CREATE) {
final String mimeType = getIntent().getType();
final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
@@ -156,12 +145,7 @@
// In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
// talkback from reading aloud the default title, we clear it here.
setTitle("");
- if (mState.action == ACTION_BROWSE) {
- final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
- } else {
- new RestoreStackTask().execute();
- }
+ new RestoreStackTask().execute();
} else {
onCurrentDirectoryChanged(ANIM_NONE);
}
@@ -181,8 +165,6 @@
state.action = ACTION_GET_CONTENT;
} else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
state.action = ACTION_OPEN_TREE;
- } else if (DocumentsContract.ACTION_BROWSE_DOCUMENT_ROOT.equals(action)) {
- state.action = ACTION_BROWSE;
} else if (DocumentsIntent.ACTION_OPEN_COPY_DESTINATION.equals(action)) {
state.action = ACTION_OPEN_COPY_DESTINATION;
}
@@ -192,20 +174,6 @@
Intent.EXTRA_ALLOW_MULTIPLE, false);
}
- if (state.action == ACTION_BROWSE) {
- state.acceptMimes = new String[] { "*/*" };
- state.allowMultiple = true;
- } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
- state.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
- } else {
- state.acceptMimes = new String[] { intent.getType() };
- }
-
- if (state.action == ACTION_BROWSE) {
- state.showSize = true;
- } else {
- state.showSize = LocalPreferences.getDisplayFileSize(this);
- }
if (state.action == ACTION_OPEN_COPY_DESTINATION) {
state.directoryCopy = intent.getBooleanExtra(
BaseActivity.DocumentsIntent.EXTRA_DIRECTORY_COPY, false);
@@ -357,11 +325,7 @@
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- // File size is locked visible for browse because that is the action triggered by Settings,
- // where the user is trying to find large files to clean up.
- // TODO: instead of setting this according to the action, use a local preference, but
- // provide a @hide extra to let callers like Settings force-enable size visibility.
- boolean fileSizeVisible = mState.action != ACTION_BROWSE;
+ boolean fileSizeVisible = mState.showSize && !mState.forceSize;
if (mState.action == ACTION_CREATE
|| mState.action == ACTION_OPEN_TREE
|| mState.action == ACTION_OPEN_COPY_DESTINATION) {
@@ -383,11 +347,9 @@
createDir.setVisible(false);
}
- advanced.setVisible(mState.action != ACTION_BROWSE && !mState.forceAdvanced);
+ advanced.setVisible(!mState.forceAdvanced);
fileSize.setVisible(fileSizeVisible);
-
- settings.setVisible(mState.action == ACTION_BROWSE
- && (root.flags & Root.FLAG_HAS_SETTINGS) != 0);
+ settings.setVisible(false);
return true;
}
@@ -446,11 +408,11 @@
}
void onSaveRequested(DocumentInfo replaceTarget) {
- new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(replaceTarget.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
}
void onSaveRequested(String mimeType, String displayName) {
- new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
+ new CreateFinishTask(mimeType, displayName).executeOnExecutor(getExecutorForCurrentDirectory());
}
@Override
@@ -466,21 +428,10 @@
openDirectory(doc);
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
// Explicit file picked, return
- new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(doc.derivedUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
- } else if (mState.action == ACTION_BROWSE) {
- // Go straight to viewing
- final Intent view = new Intent(Intent.ACTION_VIEW);
- view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- view.setData(doc.derivedUri);
-
- try {
- startActivity(view);
- } catch (ActivityNotFoundException ex) {
- Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
- }
}
}
@@ -492,7 +443,7 @@
for (int i = 0; i < size; i++) {
uris[i] = docs.get(i).derivedUri;
}
- new ExistingFinishTask(uris).executeOnExecutor(getCurrentExecutor());
+ new ExistingFinishTask(uris).executeOnExecutor(getExecutorForCurrentDirectory());
}
}
@@ -507,7 +458,7 @@
// Should not be reached.
throw new IllegalStateException("Invalid mState.action.");
}
- new PickFinishTask(result).executeOnExecutor(getCurrentExecutor());
+ new PickFinishTask(result).executeOnExecutor(getExecutorForCurrentDirectory());
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index c1362c8..7e9531b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -16,8 +16,9 @@
package com.android.documentsui;
-import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.internal.util.Preconditions.checkArgument;
import android.app.Activity;
import android.app.FragmentManager;
@@ -25,11 +26,9 @@
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.ContentValues;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.DocumentsContract;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.KeyEvent;
@@ -46,7 +45,6 @@
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
import com.android.documentsui.model.RootInfo;
-import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,7 +56,6 @@
public class FilesActivity extends BaseActivity {
public static final String TAG = "FilesActivity";
- static final boolean DEBUG = false;
private Toolbar mToolbar;
private Spinner mToolbarStack;
@@ -74,8 +71,6 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- final Context context = this;
-
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mStackAdapter = new StackAdapter();
@@ -90,7 +85,16 @@
RootsFragment.show(getFragmentManager(), null);
if (!mState.restored) {
- new RestoreStackTask().execute();
+ Uri rootUri = getIntent().getData();
+
+ // If we've got a specific root to display, restore that root using a dedicated
+ // authority. That way a misbehaving provider won't result in an ANR.
+ if (rootUri != null) {
+ new RestoreRootTask(rootUri).executeOnExecutor(
+ ProviderExecutor.forAuthority(rootUri.getAuthority()));
+ } else {
+ new RestoreStackTask().execute();
+ }
// Show a failure dialog if there was a failed operation.
final Intent intent = getIntent();
@@ -115,22 +119,16 @@
final Intent intent = getIntent();
- state.action = State.ACTION_BROWSE_ALL;
- state.acceptMimes = new String[] { intent.getType() };
+ state.action = State.ACTION_BROWSE;
state.allowMultiple = true;
- // These options are specific to the DocumentsActivity.
- Preconditions.checkArgument(
- !intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
- Preconditions.checkArgument(
- !intent.hasExtra(DocumentsContract.EXTRA_SHOW_ADVANCED));
-
- state.showAdvanced = LocalPreferences.getDisplayAdvancedDevices(this);
- state.showSize = LocalPreferences.getDisplayFileSize(this);
+ // Options specific to the DocumentsActivity.
+ checkArgument(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY));
final DocumentStack stack = intent.getParcelableExtra(CopyService.EXTRA_STACK);
- if (stack != null)
+ if (stack != null) {
state.stack = stack;
+ }
return state;
}
@@ -142,6 +140,21 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+
+ final RootInfo root = getCurrentRoot();
+
+ // If we're browsing a specific root, and that root went away, then we
+ // have no reason to hang around.
+ // TODO: Rather than just disappearing, maybe we should inform
+ // the user what has happened, let them close us. Less surprising.
+ if (mRoots.getRootBlocking(root.authority, root.rootId) == null) {
+ finish();
+ }
+ }
+
+ @Override
public void updateActionBar() {
final RootInfo root = getCurrentRoot();
@@ -194,12 +207,8 @@
public boolean onPrepareOptionsMenu(Menu menu) {
boolean shown = super.onPrepareOptionsMenu(menu);
- menu.findItem(R.id.menu_file_size).setVisible(true);
- menu.findItem(R.id.menu_advanced).setVisible(true);
-
final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
- final MenuItem settings = menu.findItem(R.id.menu_settings);
boolean canCreateDir = canCreateDirectory();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index 798992b..f5b1d8e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -87,7 +87,7 @@
// talkback from reading aloud the default title, we clear it here.
setTitle("");
final Uri rootUri = getIntent().getData();
- new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
+ new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
} else {
onCurrentDirectoryChanged(ANIM_NONE);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 5930056..5839943 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -45,6 +45,8 @@
import com.android.documentsui.Events.InputEvent;
import com.android.documentsui.Events.MotionInputEvent;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -113,8 +115,11 @@
}
};
- CompositeOnGestureListener<? extends Object> compositeListener =
- new CompositeOnGestureListener<>(listener, gestureDelegate);
+ CompositeOnGestureListener compositeListener =
+ new CompositeOnGestureListener(
+ Lists.<OnGestureListener>newArrayList(listener, gestureDelegate),
+ Lists.<OnDoubleTapListener>newArrayList(listener, gestureDelegate));
+
final GestureDetector detector =
new GestureDetector(recyclerView.getContext(), compositeListener);
@@ -1060,21 +1065,23 @@
* @template A gestureDelegate that implements both {@link OnGestureListener}
* and {@link OnDoubleTapListener}
*/
- private static final class
- CompositeOnGestureListener<L extends OnGestureListener & OnDoubleTapListener>
+ private static final class CompositeOnGestureListener
implements OnGestureListener, OnDoubleTapListener {
- private L[] mListeners;
+ private List<OnGestureListener> mGestureListeners;
+ private List<OnDoubleTapListener> mTapListeners;
- @SafeVarargs
- public CompositeOnGestureListener(L... listeners) {
- mListeners = listeners;
+ public CompositeOnGestureListener(
+ List<OnGestureListener> gestureListeners,
+ List<OnDoubleTapListener> tapListeners) {
+ mGestureListeners = gestureListeners;
+ mTapListeners = tapListeners;
}
@Override
public boolean onDown(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDown(e)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onDown(e)) {
return true;
}
}
@@ -1083,15 +1090,15 @@
@Override
public void onShowPress(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- mListeners[i].onShowPress(e);
+ for (OnGestureListener l : mGestureListeners) {
+ l.onShowPress(e);
}
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onSingleTapUp(e)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onSingleTapUp(e)) {
return true;
}
}
@@ -1100,8 +1107,8 @@
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onScroll(e1, e2, distanceX, distanceY)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onScroll(e1, e2, distanceX, distanceY)) {
return true;
}
}
@@ -1110,15 +1117,15 @@
@Override
public void onLongPress(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- mListeners[i].onLongPress(e);
+ for (OnGestureListener l : mGestureListeners) {
+ l.onLongPress(e);
}
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onFling(e1, e2, velocityX, velocityY)) {
+ for (OnGestureListener l : mGestureListeners) {
+ if (l.onFling(e1, e2, velocityX, velocityY)) {
return true;
}
}
@@ -1127,8 +1134,8 @@
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onSingleTapConfirmed(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onSingleTapConfirmed(e)) {
return true;
}
}
@@ -1137,8 +1144,8 @@
@Override
public boolean onDoubleTap(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDoubleTap(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onDoubleTap(e)) {
return true;
}
}
@@ -1147,8 +1154,8 @@
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
- for (int i = 0; i < mListeners.length; i++) {
- if (mListeners[i].onDoubleTapEvent(e)) {
+ for (OnDoubleTapListener listener : mTapListeners) {
+ if (listener.onDoubleTapEvent(e)) {
return true;
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 05f7d8d..cb46bca 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -17,6 +17,7 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.Shared.DEBUG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -58,8 +59,6 @@
* Cache of known storage backends and their roots.
*/
public class RootsCache {
- private static final boolean LOGD = false;
-
public static final Uri sNotificationUri = Uri.parse(
"content://com.android.documentsui.roots/");
@@ -91,7 +90,7 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
- if (LOGD) Log.d(TAG, "Updating roots due to change at " + uri);
+ if (DEBUG) Log.d(TAG, "Updating roots due to change at " + uri);
updateAuthorityAsync(uri.getAuthority());
}
}
@@ -148,7 +147,7 @@
final ContentResolver resolver = mContext.getContentResolver();
synchronized (mLock) {
for (String authority : mStoppedAuthorities) {
- if (LOGD) Log.d(TAG, "Loading stopped authority " + authority);
+ if (DEBUG) Log.d(TAG, "Loading stopped authority " + authority);
mRoots.putAll(authority, loadRootsForAuthority(resolver, authority));
}
mStoppedAuthorities.clear();
@@ -199,7 +198,8 @@
}
final long delta = SystemClock.elapsedRealtime() - start;
- Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
+ if (DEBUG)
+ Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
synchronized (mLock) {
mRoots = mTaskRoots;
mStoppedAuthorities = mTaskStoppedAuthorities;
@@ -213,7 +213,7 @@
// Ignore stopped packages for now; we might query them
// later during UI interaction.
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
- if (LOGD) Log.d(TAG, "Ignoring stopped authority " + info.authority);
+ if (DEBUG) Log.d(TAG, "Ignoring stopped authority " + info.authority);
mTaskStoppedAuthorities.add(info.authority);
return;
}
@@ -223,7 +223,7 @@
if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) {
synchronized (mLock) {
if (mTaskRoots.putAll(info.authority, mRoots.get(info.authority))) {
- if (LOGD) Log.d(TAG, "Used cached roots for " + info.authority);
+ if (DEBUG) Log.d(TAG, "Used cached roots for " + info.authority);
cacheHit = true;
}
}
@@ -241,7 +241,7 @@
* Bring up requested provider and query for all active roots.
*/
private Collection<RootInfo> loadRootsForAuthority(ContentResolver resolver, String authority) {
- if (LOGD) Log.d(TAG, "Loading roots for " + authority);
+ if (DEBUG) Log.d(TAG, "Loading roots for " + authority);
synchronized (mObservedAuthorities) {
if (mObservedAuthorities.add(authority)) {
@@ -370,10 +370,15 @@
// Exclude downloads roots that don't support directory creation
// TODO: Add flag to check the root supports directory creation or not.
if (state.directoryCopy && root.isDownloads()) continue;
- // Only show empty roots when creating
- if ((state.action != State.ACTION_CREATE ||
+
+ // Only show empty roots when creating, or in browse mode.
+ if (empty && (state.action != State.ACTION_BROWSE ||
+ state.action != State.ACTION_CREATE ||
state.action != State.ACTION_OPEN_TREE ||
- state.action != State.ACTION_OPEN_COPY_DESTINATION) && empty) continue;
+ state.action != State.ACTION_OPEN_COPY_DESTINATION)) {
+ if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
+ continue;
+ }
// Only include roots that serve requested content
final boolean overlap =
@@ -385,7 +390,7 @@
// Exclude roots from the calling package.
if (state.excludedAuthorities.contains(root.authority)) {
- if (LOGD) Log.d(TAG, "Excluding root " + root.authority + " from calling package.");
+ if (DEBUG) Log.d(TAG, "Excluding root " + root.authority + " from calling package.");
continue;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 0c1ebc1..9c884d4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -22,7 +22,7 @@
* @hide
*/
public final class Shared {
- public static final boolean DEBUG = false;
+ public static final boolean DEBUG = true;
public static final String TAG = "Documents";
/**
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index aeac912..2033159 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
@@ -96,6 +97,12 @@
}
@Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ resetState();
+ }
+
+ @Override
protected int getPromtReasonStringRes(int reason) {
// No message on SIM Pin
return 0;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index e342865..57ee319 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -121,7 +121,6 @@
private static final int MSG_DEVICE_PROVISIONED = 308;
private static final int MSG_DPM_STATE_CHANGED = 309;
private static final int MSG_USER_SWITCHING = 310;
- private static final int MSG_KEYGUARD_VISIBILITY_CHANGED = 311;
private static final int MSG_KEYGUARD_RESET = 312;
private static final int MSG_BOOT_COMPLETED = 313;
private static final int MSG_USER_SWITCH_COMPLETE = 314;
@@ -233,9 +232,6 @@
case MSG_USER_SWITCH_COMPLETE:
handleUserSwitchComplete(msg.arg1);
break;
- case MSG_KEYGUARD_VISIBILITY_CHANGED:
- handleKeyguardVisibilityChanged(msg.arg1);
- break;
case MSG_KEYGUARD_RESET:
handleKeyguardReset();
break;
@@ -1344,19 +1340,20 @@
}
/**
- * Handle {@link #MSG_KEYGUARD_VISIBILITY_CHANGED}
+ * Notifies that the visibility state of Keyguard has changed.
+ *
+ * <p>Needs to be called from the main thread.
*/
- private void handleKeyguardVisibilityChanged(int showing) {
- if (DEBUG) Log.d(TAG, "handleKeyguardVisibilityChanged(" + showing + ")");
- boolean isShowing = (showing == 1);
- mKeyguardIsVisible = isShowing;
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
+ mKeyguardIsVisible = showing;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onKeyguardVisibilityChangedRaw(isShowing);
+ cb.onKeyguardVisibilityChangedRaw(showing);
}
}
- if (!isShowing) {
+ if (!showing) {
mFingerprintAlreadyAuthenticated = false;
}
updateFingerprintListeningState();
@@ -1477,13 +1474,6 @@
}
}
- public void sendKeyguardVisibilityChanged(boolean showing) {
- if (DEBUG) Log.d(TAG, "sendKeyguardVisibilityChanged(" + showing + ")");
- Message message = mHandler.obtainMessage(MSG_KEYGUARD_VISIBILITY_CHANGED);
- message.arg1 = showing ? 1 : 0;
- message.sendToTarget();
- }
-
public void sendKeyguardReset() {
mHandler.obtainMessage(MSG_KEYGUARD_RESET).sendToTarget();
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 1d71346..e12e3a5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -166,7 +166,7 @@
.putExtra(Intent.EXTRA_SETTING_NAME, name)
.putExtra(Intent.EXTRA_SETTING_NEW_VALUE, value)
.putExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE, oldValue);
- context.sendBroadcastAsUser(intent, UserHandle.OWNER, null);
+ context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 7449009..5bf251b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -159,7 +159,9 @@
if (mServicesStarted) {
int len = mServices.length;
for (int i = 0; i < len; i++) {
- mServices[i].onConfigurationChanged(newConfig);
+ if (mServices[i] != null) {
+ mServices[i].onConfigurationChanged(newConfig);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
index 5cd914f..8c681fc 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
@@ -16,7 +16,6 @@
package com.android.systemui.classifier;
-import android.hardware.SensorEvent;
import android.view.MotionEvent;
import java.lang.Math;
@@ -27,27 +26,19 @@
/**
* A classifier which calculates the variance of differences between successive angles in a stroke.
- * For each stroke it keeps its last three points. If some successive points are the same, it ignores
- * the repetitions. If a new point is added, the classifier calculates the angle between the last
- * three points. After that it calculates the difference between this angle and the previously
- * calculated angle. The return value of the classifier is the variance of the differences
- * from a stroke. If there are multiple strokes created at once, the classifier sums up the
- * variances of all the strokes. Also the value is multiplied by HISTORY_FACTOR after each
- * INTERVAL milliseconds.
+ * For each stroke it keeps its last three points. If some successive points are the same, it
+ * ignores the repetitions. If a new point is added, the classifier calculates the angle between
+ * the last three points. After that, it calculates the difference between this angle and the
+ * previously calculated angle. The return value of the classifier is the variance of the
+ * differences from a stroke. To the differences there is artificially added value 0.0 and the
+ * difference between the first angle and PI (angles are in radians). It helps with strokes which
+ * have few points and punishes more strokes which are not smooth.
*/
-public class AnglesVarianceClassifier extends Classifier {
- private final float INTERVAL = 10.0f;
- private final float CLEAR_HISTORY = 500f;
- private final float HISTORY_FACTOR = 0.9f;
-
+public class AnglesVarianceClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
- private float mValue;
- private long mLastUpdate;
public AnglesVarianceClassifier(ClassifierData classifierData) {
mClassifierData = classifierData;
- mValue = 0.0f;
- mLastUpdate = System.currentTimeMillis();
}
@Override
@@ -65,40 +56,12 @@
mStrokeMap.put(stroke, new Data());
}
mStrokeMap.get(stroke).addPoint(stroke.getPoints().get(stroke.getPoints().size() - 1));
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
- || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
- decayValue();
- mValue += mStrokeMap.get(stroke).getAnglesVariance();
- }
}
}
- /**
- * Decreases mValue through time
- */
- private void decayValue() {
- long currentTimeMillis = System.currentTimeMillis();
- if (currentTimeMillis - mLastUpdate > CLEAR_HISTORY) {
- mValue = 0.0f;
- } else {
- mValue *= Math.pow(HISTORY_FACTOR, (float) (currentTimeMillis - mLastUpdate) / INTERVAL);
- }
- mLastUpdate = currentTimeMillis;
- }
-
@Override
- public void onSensorChanged(SensorEvent event) {
- }
-
- @Override
- public float getFalseTouchEvaluation(int type) {
- decayValue();
- float currentValue = 0.0f;
- for (Data data: mStrokeMap.values()) {
- currentValue += data.getAnglesVariance();
- }
- return (float) (mValue + currentValue);
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return mStrokeMap.get(stroke).getAnglesVariance();
}
private class Data {
@@ -150,7 +113,7 @@
}
public float getAnglesVariance() {
- return mSumSquares / mCount + (mSum / mCount) * (mSum / mCount);
+ return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
index b76be14..89d20de 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java
@@ -20,7 +20,7 @@
import android.view.MotionEvent;
/**
- * An interface for classifiers for touch and sensor events.
+ * An abstract class for classifiers for touch and sensor events.
*/
public abstract class Classifier {
public static final int QUICK_SETTINGS = 0;
@@ -30,6 +30,7 @@
public static final int UNLOCK = 4;
public static final int LEFT_AFFORDANCE = 5;
public static final int RIGHT_AFFORDANCE = 6;
+ public static final int GENERIC = 7;
/**
* Contains all the information about touch events from which the classifier can query
@@ -47,11 +48,4 @@
*/
public void onSensorChanged(SensorEvent event) {
}
-
- /**
- * @param type the type of action for which this method is called
- * @return a nonnegative value which is used to determine whether this a false touch. The
- * bigger the value the greater the chance that this a false touch.
- */
- public abstract float getFalseTouchEvaluation(int type);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
index 77b81d2..bccad4e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
@@ -19,21 +19,26 @@
import android.util.SparseArray;
import android.view.MotionEvent;
+import java.util.ArrayList;
+
/**
* Contains data which is used to classify interaction sequences on the lockscreen. It does, for
* example, provide information on the current touch state.
*/
public class ClassifierData {
private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
+ private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
public ClassifierData() {
}
public void update(MotionEvent event) {
+ mEndingStrokes.clear();
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
mCurrentStrokes.clear();
}
+
for (int i = 0; i < event.getPointerCount(); i++) {
int id = event.getPointerId(i);
if (mCurrentStrokes.get(id) == null) {
@@ -41,10 +46,16 @@
}
mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
event.getEventTimeNano());
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
+ || (action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
+ mEndingStrokes.add(getStroke(id));
+ }
}
}
public void cleanUp(MotionEvent event) {
+ mEndingStrokes.clear();
int action = event.getActionMasked();
for (int i = 0; i < event.getPointerCount(); i++) {
int id = event.getPointerId(i);
@@ -56,6 +67,13 @@
}
/**
+ * @return the list of Strokes which are ending in the recently added MotionEvent
+ */
+ public ArrayList<Stroke> getEndingStrokes() {
+ return mEndingStrokes;
+ }
+
+ /**
* @param id the id from MotionEvent
* @return the Stroke assigned to the id
*/
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 347273a..c68fff8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -126,11 +126,10 @@
}
/**
- * @param type the type of action for which this method is called
* @return true if the classifier determined that this is not a human interacting with the phone
*/
- public boolean isFalseTouch(int type) {
- return mHumanInteractionClassifier.getFalseTouchEvaluation(type) > 0.5;
+ public boolean isFalseTouch() {
+ return mHumanInteractionClassifier.isFalseTouch();
}
@Override
@@ -189,6 +188,7 @@
}
public void onQsDown() {
+ mHumanInteractionClassifier.setType(Classifier.QUICK_SETTINGS);
mDataCollector.onQsDown();
}
@@ -197,6 +197,7 @@
}
public void onTrackingStarted() {
+ mHumanInteractionClassifier.setType(Classifier.UNLOCK);
mDataCollector.onTrackingStarted();
}
@@ -217,6 +218,7 @@
}
public void onNotificatonStartDraggingDown() {
+ mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DRAG_DOWN);
mDataCollector.onNotificatonStartDraggingDown();
}
@@ -229,6 +231,7 @@
}
public void onNotificatonStartDismissing() {
+ mHumanInteractionClassifier.setType(Classifier.NOTIFICATION_DISMISS);
mDataCollector.onNotificatonStartDismissing();
}
@@ -245,6 +248,11 @@
}
public void onAffordanceSwipingStarted(boolean rightCorner) {
+ if (rightCorner) {
+ mHumanInteractionClassifier.setType(Classifier.RIGHT_AFFORDANCE);
+ } else {
+ mHumanInteractionClassifier.setType(Classifier.LEFT_AFFORDANCE);
+ }
mDataCollector.onAffordanceSwipingStarted(rightCorner);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
new file mode 100644
index 0000000..e7f4c35
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * An abstract class for classifiers which classify the whole gesture (all the strokes which
+ * occurred from DOWN event to UP/CANCEL event)
+ */
+public abstract class GestureClassifier extends Classifier {
+
+ /**
+ * @param type the type of action for which this method is called
+ * @return a non-negative value which is used to determine whether the most recent gesture is a
+ * false interaction. The bigger the value the greater the chance that this a false
+ * interaction.
+ */
+ public abstract float getFalseTouchEvaluation(int type);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
new file mode 100644
index 0000000..b057bda
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+import java.util.ArrayList;
+
+/**
+ * Holds the evaluations for ended strokes and gestures. These values are decreased through time.
+ */
+public class HistoryEvaluator {
+ private static final float INTERVAL = 50.0f;
+ private static final float HISTORY_FACTOR = 0.9f;
+ private static final float EPSILON = 1e-5f;
+
+ private final ArrayList<Data> mStrokes = new ArrayList<>();
+ private final ArrayList<Data> mGestureWeights = new ArrayList<>();
+ private long mLastUpdate;
+
+ public HistoryEvaluator() {
+ mLastUpdate = System.currentTimeMillis();
+ }
+
+ public void addStroke(float evaluation) {
+ decayValue();
+ mStrokes.add(new Data(evaluation));
+ }
+
+ public void addGesture(float evaluation) {
+ decayValue();
+ mGestureWeights.add(new Data(evaluation));
+ }
+
+ /**
+ * Calculates the weighted average of strokes and adds to it the weighted average of gestures
+ */
+ public float getEvaluation() {
+ return weightedAverage(mStrokes) + weightedAverage(mGestureWeights);
+ }
+
+ private float weightedAverage(ArrayList<Data> list) {
+ float sumValue = 0.0f;
+ float sumWeight = 0.0f;
+ int size = list.size();
+ for (int i = 0; i < size; i++) {
+ Data data = list.get(i);
+ sumValue += data.evaluation * data.weight;
+ sumWeight += data.weight;
+ }
+
+ if (sumWeight == 0.0f) {
+ return 0.0f;
+ }
+
+ return sumValue / sumWeight;
+ }
+
+ private void decayValue() {
+ long currentTimeMillis = System.currentTimeMillis();
+
+ // All weights are multiplied by HISTORY_FACTOR after each INTERVAL milliseconds.
+ float factor = (float) Math.pow(HISTORY_FACTOR,
+ (float) (currentTimeMillis - mLastUpdate) / INTERVAL);
+
+ decayValue(mStrokes, factor);
+ decayValue(mGestureWeights, factor);
+ mLastUpdate = currentTimeMillis;
+ }
+
+ private void decayValue(ArrayList<Data> list, float factor) {
+ int size = list.size();
+ for (int i = 0; i < size; i++) {
+ list.get(i).weight *= factor;
+ }
+
+ // Removing evaluations with such small weights that they do not matter anymore
+ while (!list.isEmpty() && isZero(list.get(0).weight)) {
+ list.remove(0);
+ }
+ }
+
+ private boolean isZero(float x) {
+ return x <= EPSILON && x >= -EPSILON;
+ }
+
+ /**
+ * For each stroke it holds its initial value and the current weight. Initially the
+ * weight is set to 1.0
+ */
+ private class Data {
+ public float evaluation;
+ public float weight;
+
+ public Data(float evaluation) {
+ this.evaluation = evaluation;
+ weight = 1.0f;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index a5f6df85..86ea640 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -25,6 +25,8 @@
import android.provider.Settings;
import android.view.MotionEvent;
+import java.util.ArrayList;
+
/**
* An classifier trying to determine whether it is a human interacting with the phone or not.
*/
@@ -35,8 +37,14 @@
private final Handler mHandler = new Handler();
private final Context mContext;
- private AnglesVarianceClassifier mAnglesVarianceClassifier;
+ private ArrayList<StrokeClassifier> mStrokeClassifiers = new ArrayList<>();
+ private ArrayList<GestureClassifier> mGestureClassifiers = new ArrayList<>();
+ private final int mStrokeClassifiersSize;
+ private final int mGestureClassifiersSize;
+
+ private HistoryEvaluator mHistoryEvaluator;
private boolean mEnableClassifier = false;
+ private int mCurrentType = Classifier.GENERIC;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
@@ -48,7 +56,12 @@
private HumanInteractionClassifier(Context context) {
mContext = context;
mClassifierData = new ClassifierData();
- mAnglesVarianceClassifier = new AnglesVarianceClassifier(mClassifierData);
+ mHistoryEvaluator = new HistoryEvaluator();
+
+ mStrokeClassifiers.add(new AnglesVarianceClassifier(mClassifierData));
+
+ mStrokeClassifiersSize = mStrokeClassifiers.size();
+ mGestureClassifiersSize = mGestureClassifiers.size();
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(HIC_ENABLE), false,
@@ -71,11 +84,44 @@
HIC_ENABLE, 0);
}
+ public void setType(int type) {
+ mCurrentType = type;
+ }
+
@Override
public void onTouchEvent(MotionEvent event) {
if (mEnableClassifier) {
mClassifierData.update(event);
- mAnglesVarianceClassifier.onTouchEvent(event);
+
+ for (int i = 0; i < mStrokeClassifiersSize; i++) {
+ mStrokeClassifiers.get(i).onTouchEvent(event);
+ }
+
+ for (int i = 0; i < mGestureClassifiersSize; i++) {
+ mGestureClassifiers.get(i).onTouchEvent(event);
+ }
+
+ int size = mClassifierData.getEndingStrokes().size();
+ for (int i = 0; i < size; i++) {
+ Stroke stroke = mClassifierData.getEndingStrokes().get(i);
+ float evaluation = 0.0f;
+ for (int j = 0; j < mStrokeClassifiersSize; j++) {
+ evaluation += mStrokeClassifiers.get(j).getFalseTouchEvaluation(
+ mCurrentType, stroke);
+ }
+ mHistoryEvaluator.addStroke(evaluation);
+ }
+
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ float evaluation = 0.0f;
+ for (int i = 0; i < mGestureClassifiersSize; i++) {
+ evaluation += mGestureClassifiers.get(i).getFalseTouchEvaluation(mCurrentType);
+ }
+ mHistoryEvaluator.addGesture(evaluation);
+ setType(Classifier.GENERIC);
+ }
+
mClassifierData.cleanUp(event);
}
}
@@ -84,12 +130,8 @@
public void onSensorChanged(SensorEvent event) {
}
- @Override
- public float getFalseTouchEvaluation(int type) {
- if (mEnableClassifier) {
- return mAnglesVarianceClassifier.getFalseTouchEvaluation(type);
- }
- return 0.0f;
+ public boolean isFalseTouch() {
+ return mHistoryEvaluator.getEvaluation() >= 5.0f;
}
public boolean isEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
index f386cbe4..8c3fdd4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
@@ -19,7 +19,8 @@
import java.util.ArrayList;
/**
- * Contains data about movement traces (pointers)
+ * Contains data about a stroke (a single trace, all the events from a given id from the
+ * DOWN/POINTER_DOWN event till the UP/POINTER_UP/CANCEL event.)
*/
public class Stroke {
private ArrayList<Point> mPoints = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
new file mode 100644
index 0000000..d561f46
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.classifier;
+
+/**
+ * An abstract class for classifiers which classify each stroke separately.
+ */
+public abstract class StrokeClassifier extends Classifier {
+
+ /**
+ * @param type the type of action for which this method is called
+ * @param stroke the stroke for which the evaluation will be calculated
+ * @return a non-negative value which is used to determine whether this a false touch. The
+ * bigger the value the greater the chance that this a false touch.
+ */
+ public abstract float getFalseTouchEvaluation(int type, Stroke stroke);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3de5001..2ea1e43 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -921,9 +921,27 @@
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
+ } else if (!isSecure()) {
+
+ // Keyguard is not secure, no need to do anything, and we don't need to reshow
+ // the Keyguard after the client releases the Keyguard lock.
+ mExternallyEnabled = true;
+ mNeedToReshowWhenReenabled = false;
+ updateInputRestricted();
+ try {
+ callback.onKeyguardExitResult(true);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
} else {
- mExitSecureCallback = callback;
- verifyUnlockLocked();
+
+ // Since we prevent apps from hiding the Keyguard if we are secure, this should be
+ // a no-op as well.
+ try {
+ callback.onKeyguardExitResult(false);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 7f68e29..f39f302 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -160,7 +160,7 @@
throw new SecurityException("Async playback only available from system UID.");
}
if (UserHandle.ALL.equals(user)) {
- user = UserHandle.OWNER;
+ user = UserHandle.SYSTEM;
}
mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
index 87194fb..b157275 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.tiles;
import com.android.systemui.qs.QSTileView;
+import com.android.systemui.statusbar.policy.WifiIcons;
/** Quick settings tile: Wifi **/
public class QWifiTile extends WifiTile {
@@ -29,4 +30,23 @@
public int getTileType() {
return QSTileView.QS_TYPE_QUICK;
}
+
+ @Override
+ protected void handleUpdateState(SignalState state, Object arg) {
+ super.handleUpdateState(state, arg);
+
+ CallbackInfo cb = (CallbackInfo) arg;
+ if (cb == null) {
+ cb = mSignalCallback.mInfo;
+ }
+ boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
+
+ if (state.enabled && wifiConnected) {
+ // Only show full signal here.
+ state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][4]);
+ }
+ // No activity in the quick toggle.
+ state.activityIn = false;
+ state.activityOut = false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 3295e14..91e0218 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -48,7 +48,7 @@
private final WifiDetailAdapter mDetailAdapter;
private final QSTile.SignalState mStateBeforeClick = newTileState();
- private final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
+ protected final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
private final boolean mAlwaysDetail;
@@ -200,7 +200,7 @@
return string;
}
- private static final class CallbackInfo {
+ protected static final class CallbackInfo {
boolean enabled;
boolean connected;
int wifiSignalIconId;
@@ -223,7 +223,7 @@
}
}
- private final class WifiSignalCallback extends SignalCallbackAdapter {
+ protected final class WifiSignalCallback extends SignalCallbackAdapter {
final CallbackInfo mInfo = new CallbackInfo();
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 5a2fa3b..1d890d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -33,7 +33,7 @@
private static final String TAG = "DozeParameters";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final int MAX_DURATION = 10 * 1000;
+ private static final int MAX_DURATION = 60 * 1000;
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 13d0e1e..3feead8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -610,7 +610,7 @@
if (!mStatusBar.isFalsingThresholdNeeded()) {
return false;
}
- if (mFalsingManager.isFalseTouch(Classifier.UNLOCK)) {
+ if (mFalsingManager.isFalseTouch()) {
return true;
}
if (!mTouchAboveFalsingThreshold) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 394ff3f..05f6e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -466,7 +466,7 @@
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if ((showing && !occluded) != (mLastShowing && !mLastOccluded) || mFirstUpdate) {
- updateMonitor.sendKeyguardVisibilityChanged(showing && !occluded);
+ updateMonitor.onKeyguardVisibilityChanged(showing && !occluded);
}
if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
updateMonitor.sendKeyguardBouncerChanged(bouncerShowing);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index c56646f..374408d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -18,7 +18,7 @@
import com.android.systemui.R;
-class WifiIcons {
+public class WifiIcons {
static final int[][] WIFI_SIGNAL_STRENGTH = {
{ R.drawable.stat_sys_wifi_signal_0,
R.drawable.stat_sys_wifi_signal_1,
@@ -32,7 +32,7 @@
R.drawable.stat_sys_wifi_signal_4_fully }
};
- static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
+ public static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
{ R.drawable.ic_qs_wifi_0,
R.drawable.ic_qs_wifi_1,
R.drawable.ic_qs_wifi_2,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index b2f527e..da19b06 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -89,7 +89,6 @@
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
private static final int WAIT_FOR_RIPPLE = 200;
- private static final int UPDATE_ANIMATION_DURATION = 80;
private final Context mContext;
private final H mHandler = new H();
@@ -353,14 +352,6 @@
writer.println(mAccessibility.mFeedbackEnabled);
}
- private static int getImpliedLevel(SeekBar seekBar, int progress) {
- final int m = seekBar.getMax();
- final int n = m / 100 - 1;
- final int level = progress == 0 ? 0
- : progress == m ? (m / 100) : (1 + (int)((progress / (float) m) * n));
- return level;
- }
-
@SuppressLint("InflateParams")
private VolumeRow initRow(final int stream, int iconRes, int iconMuteRes, boolean important) {
final VolumeRow row = new VolumeRow();
@@ -690,7 +681,7 @@
: false;
// update slider max
- final int max = ss.levelMax * 100;
+ final int max = ss.levelMax;
if (max != row.slider.getMax()) {
row.slider.setMax(max);
}
@@ -777,8 +768,7 @@
if (row.tracking) {
return; // don't update if user is sliding
}
- final int progress = row.slider.getProgress();
- final int level = getImpliedLevel(row.slider, progress);
+ final int level = row.slider.getProgress();
final boolean rowVisible = row.view.getVisibility() == View.VISIBLE;
final boolean inGracePeriod = (SystemClock.uptimeMillis() - row.userAttempt)
< USER_ATTEMPT_GRACE_PERIOD;
@@ -794,33 +784,7 @@
return; // don't clamp if visible
}
}
- final int newProgress = vlevel * 100;
- if (progress != newProgress) {
- if (mShowing && rowVisible) {
- // animate!
- if (row.anim != null && row.anim.isRunning()
- && row.animTargetProgress == newProgress) {
- return; // already animating to the target progress
- }
- // start/update animation
- if (row.anim == null) {
- row.anim = ObjectAnimator.ofInt(row.slider, "progress", progress, newProgress);
- row.anim.setInterpolator(new DecelerateInterpolator());
- } else {
- row.anim.cancel();
- row.anim.setIntValues(progress, newProgress);
- }
- row.animTargetProgress = newProgress;
- row.anim.setDuration(UPDATE_ANIMATION_DURATION);
- row.anim.start();
- } else {
- // update slider directly to clamped value
- if (row.anim != null) {
- row.anim.cancel();
- }
- row.slider.setProgress(newProgress);
- }
- }
+ row.slider.setProgress(vlevel, true);
}
private void recheckH(VolumeRow row) {
@@ -1025,20 +989,19 @@
+ " onProgressChanged " + progress + " fromUser=" + fromUser);
if (!fromUser) return;
if (mRow.ss.levelMin > 0) {
- final int minProgress = mRow.ss.levelMin * 100;
+ final int minProgress = mRow.ss.levelMin;
if (progress < minProgress) {
seekBar.setProgress(minProgress);
progress = minProgress;
}
}
- final int userLevel = getImpliedLevel(seekBar, progress);
- if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) {
+ if (mRow.ss.level != progress || mRow.ss.muted && progress > 0) {
mRow.userAttempt = SystemClock.uptimeMillis();
- if (mRow.requestedLevel != userLevel) {
- mController.setStreamVolume(mRow.stream, userLevel);
- mRow.requestedLevel = userLevel;
+ if (mRow.requestedLevel != progress) {
+ mController.setStreamVolume(mRow.stream, progress);
+ mRow.requestedLevel = progress;
Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_CHANGED, mRow.stream,
- userLevel);
+ progress);
}
}
}
@@ -1055,7 +1018,7 @@
if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream);
mRow.tracking = false;
mRow.userAttempt = SystemClock.uptimeMillis();
- int userLevel = getImpliedLevel(seekBar, seekBar.getProgress());
+ final int userLevel = seekBar.getProgress();
Events.writeEvent(mContext, Events.EVENT_TOUCH_LEVEL_DONE, mRow.stream, userLevel);
if (mRow.ss.level != userLevel) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(H.RECHECK, mRow),
@@ -1137,8 +1100,6 @@
private int iconState; // from Events
private boolean cachedShowHeaders = VolumePrefs.DEFAULT_SHOW_HEADERS;
private int cachedExpandButtonRes;
- private ObjectAnimator anim; // slider progress animation for non-touch-related updates
- private int animTargetProgress;
private int lastAudibleLevel = 1;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 91c3d48..ff2a2ee 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -967,8 +967,8 @@
List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
new Intent(AccessibilityService.SERVICE_INTERFACE),
- PackageManager.GET_SERVICES
- | PackageManager.GET_META_DATA
+ PackageManager.GET_SERVICES
+ | PackageManager.GET_META_DATA
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
mCurrentUserId);
@@ -3217,7 +3217,8 @@
case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
return AccessibilityWindowInfo.TYPE_SYSTEM;
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 2f4ad3f..0c6eb40 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1523,13 +1523,13 @@
private void reportPowerSaveWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
private void reportTempWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
}
void readConfigFileLocked() {
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index b9db89ec..2454487 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -170,7 +170,7 @@
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_SEND_BROADCAST) {
- getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.OWNER,
+ getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.SYSTEM,
android.Manifest.permission.READ_LOGS);
}
}
@@ -488,7 +488,7 @@
///////////////////////////////////////////////////////////////////////////
- /** Chronologically sorted list of {@link #EntryFile} */
+ /** Chronologically sorted list of {@link EntryFile} */
private static final class FileList implements Comparable<FileList> {
public int blocks = 0;
public final TreeSet<EntryFile> contents = new TreeSet<EntryFile>();
@@ -613,7 +613,7 @@
/**
* Creates a EntryFile object with only a timestamp for comparison purposes.
- * @param timestampMillis to compare with.
+ * @param millis to compare with.
*/
public EntryFile(long millis) {
this.tag = null;
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index bd7d4b2..7c85001 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -101,8 +101,7 @@
* Whether camera double tap power button gesture is currently enabled;
*/
private boolean mCameraDoubleTapPowerEnabled;
- private long mLastPowerDownWhileNonInteractive;
- private long mLastPowerDownWhileInteractive;
+ private long mLastPowerDown;
public GestureLauncherService(Context context) {
super(context);
@@ -252,35 +251,32 @@
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
boolean launched = false;
boolean intercept = false;
+ long doubleTapInterval;
synchronized (this) {
- if (!mCameraDoubleTapPowerEnabled) {
- mLastPowerDownWhileNonInteractive = 0;
- mLastPowerDownWhileInteractive = 0;
- return false;
- }
- if (event.getEventTime() - mLastPowerDownWhileNonInteractive
- < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
+ doubleTapInterval = event.getEventTime() - mLastPowerDown;
+ if (mCameraDoubleTapPowerEnabled
+ && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
launched = true;
- intercept = true;
- } else if (event.getEventTime() - mLastPowerDownWhileInteractive
- < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
- launched = true;
+ intercept = interactive;
}
- mLastPowerDownWhileNonInteractive = interactive ? 0 : event.getEventTime();
- mLastPowerDownWhileInteractive = interactive ? event.getEventTime() : 0;
+ mLastPowerDown = event.getEventTime();
}
if (launched) {
Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
- launched = handleCameraLaunchGesture(false /* useWakelock */,
- MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE);
+ launched = handleCameraLaunchGesture(false /* useWakelock */);
+ if (launched) {
+ MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
+ (int) doubleTapInterval);
+ }
}
+ MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
return intercept && launched;
}
/**
* @return true if camera was launched, false otherwise.
*/
- private boolean handleCameraLaunchGesture(boolean useWakelock, int logCategory) {
+ private boolean handleCameraLaunchGesture(boolean useWakelock) {
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
if (!userSetupComplete) {
@@ -300,7 +296,6 @@
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
service.onCameraLaunchGestureDetected();
- MetricsLogger.action(mContext, logCategory);
return true;
}
@@ -339,8 +334,8 @@
Slog.d(TAG, String.format("Received a camera launch event: " +
"values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
}
- if (handleCameraLaunchGesture(true /* useWakelock */,
- MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE)) {
+ if (handleCameraLaunchGesture(true /* useWakelock */)) {
+ MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
trackCameraLaunchEvent(event);
}
return;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 885c765..087ddd6 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -211,8 +211,8 @@
new ArrayList<LocationProviderProxy>();
// current active user on the device - other users are denied location data
- private int mCurrentUserId = UserHandle.USER_OWNER;
- private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_OWNER };
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
+ private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
public LocationManagerService(Context context) {
super();
@@ -1832,7 +1832,8 @@
// geo-fence manager uses the public location API, need to clear identity
int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) {
+ // TODO: http://b/23822629
+ if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
// temporary measure until geofences work for secondary users
Log.w(TAG, "proximity alerts are currently available only to the primary user");
return;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 540f8cb..c3d32c2 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2981,7 +2981,7 @@
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
- UserHandle.OWNER)) {
+ UserHandle.SYSTEM)) {
mBound = true;
return true;
}
@@ -3014,7 +3014,6 @@
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
handleError();
- return;
} else {
handleExecute();
if (DEBUG_OBB)
@@ -3176,8 +3175,6 @@
waitForReady();
warnOnNotMounted();
- final ObbInfo obbInfo = getObbInfo();
-
final ObbState existingState;
synchronized (mObbMounts) {
existingState = mObbPathToStateMap.get(mObbState.rawPath);
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b05a690..b984e19 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -133,8 +133,8 @@
filter.addDataSchemeSpecificPart(scorer.mPackageName,
PatternMatcher.PATTERN_LITERAL);
mReceiver = new ScorerChangedReceiver(scorer.mPackageName);
- // TODO: Need to update when we support per-user scorers.
- mContext.registerReceiverAsUser(mReceiver, UserHandle.OWNER, filter, null, null);
+ // TODO: Need to update when we support per-user scorers. http://b/23422763
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter, null, null);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Registered receiver for " + scorer.mPackageName);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6728b83..07a7af4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
@@ -2020,7 +2021,7 @@
intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
new UserHandle(userId)))
.setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0,
- deleteIntent, 0, UserHandle.OWNER))
+ deleteIntent, 0, UserHandle.SYSTEM))
.build();
try {
@@ -2378,8 +2379,8 @@
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
// User 0 is the first and only user that runs at boot.
- mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
- mUserLru.add(UserHandle.USER_OWNER);
+ mStartedUsers.put(UserHandle.USER_SYSTEM, new UserState(UserHandle.SYSTEM, true));
+ mUserLru.add(UserHandle.USER_SYSTEM);
updateStartedUserArrayLocked();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
@@ -4626,7 +4627,7 @@
// is hosted by the process... then make sure all visible
// activities are running, taking care of restarting this
// process.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
}
@@ -5646,7 +5647,7 @@
try {
// Entire package setting changed
enabled = pm.getApplicationEnabledSetting(packageName,
- (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_SYSTEM);
} catch (Exception e) {
// No such package/component; probably racing with uninstall. In any
// event it means we have nothing further to do here.
@@ -5664,7 +5665,7 @@
try {
enabled = pm.getComponentEnabledSetting(
new ComponentName(packageName, changedClass),
- (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER);
+ (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_SYSTEM);
} catch (Exception e) {
// As above, probably racing with uninstall.
return;
@@ -8664,7 +8665,7 @@
}
if (task.mResizeable != resizeable) {
task.mResizeable = resizeable;
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mStackSupervisor.resumeTopActivitiesLocked();
}
}
@@ -9108,7 +9109,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mStackSupervisor.resizeStackLocked(stackId, bounds);
+ mStackSupervisor.resizeStackLocked(stackId, bounds, !PRESERVE_WINDOWS);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -9391,7 +9392,7 @@
(ProviderInfo)providers.get(i);
boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags);
- if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_OWNER) {
+ if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) {
// This is a singleton provider, but a user besides the
// default user is asking to initialize a process it runs
// in... well, no, it doesn't actually run in this process,
@@ -9613,7 +9614,7 @@
}
}
- private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
+ private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
@@ -9641,14 +9642,14 @@
cpr = mProviderMap.getProviderByName(name, userId);
// If that didn't work, check if it exists for user 0 and then
// verify that it's a singleton provider before using it.
- if (cpr == null && userId != UserHandle.USER_OWNER) {
- cpr = mProviderMap.getProviderByName(name, UserHandle.USER_OWNER);
+ if (cpr == null && userId != UserHandle.USER_SYSTEM) {
+ cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
if (cpr != null) {
cpi = cpr.info;
if (isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
- userId = UserHandle.USER_OWNER;
+ userId = UserHandle.USER_SYSTEM;
checkCrossUser = false;
} else {
cpr = null;
@@ -9741,7 +9742,6 @@
Binder.restoreCallingIdentity(origId);
}
- boolean singleton;
if (!providerRunning) {
try {
checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
@@ -9758,11 +9758,11 @@
// (it's a call within the same user || the provider is a
// privileged app)
// Then allow connecting to the singleton provider
- singleton = isSingleton(cpi.processName, cpi.applicationInfo,
+ boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags)
&& isValidSingletonCall(r.uid, cpi.applicationInfo.uid);
if (singleton) {
- userId = UserHandle.USER_OWNER;
+ userId = UserHandle.USER_SYSTEM;
}
cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId);
checkTime(startTime, "getContentProviderImpl: got app info for user");
@@ -10365,7 +10365,7 @@
}
final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);
if (!mBooted && !mBooting
- && userId == UserHandle.USER_OWNER
+ && userId == UserHandle.USER_SYSTEM
&& (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
r.persistent = true;
}
@@ -11188,7 +11188,7 @@
final boolean translucentChanged = r.changeWindowTranslucency(true);
if (translucentChanged) {
r.task.stack.releaseBackgroundResources(r);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
mWindowManager.setAppFullscreen(token, true);
return translucentChanged;
@@ -11216,7 +11216,7 @@
if (translucentChanged) {
r.task.stack.convertActivityToTranslucent(r);
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.setAppFullscreen(token, false);
return translucentChanged;
}
@@ -11822,12 +11822,12 @@
}
private boolean deliverPreBootCompleted(final Runnable onFinishCallback,
- ArrayList<ComponentName> doneReceivers, int userId) {
+ ArrayList<ComponentName> doneReceivers) {
Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
List<ResolveInfo> ris = null;
try {
ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, userId);
+ intent, null, 0, UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
}
if (ris == null) {
@@ -11841,22 +11841,18 @@
}
intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);
- // For User 0, load the version number. When delivering to a new user, deliver
- // to all receivers.
- if (userId == UserHandle.USER_OWNER) {
- ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
- for (int i=0; i<ris.size(); i++) {
- ActivityInfo ai = ris.get(i).activityInfo;
- ComponentName comp = new ComponentName(ai.packageName, ai.name);
- if (lastDoneReceivers.contains(comp)) {
- // We already did the pre boot receiver for this app with the current
- // platform version, so don't do it again...
- ris.remove(i);
- i--;
- // ...however, do keep it as one that has been done, so we don't
- // forget about it when rewriting the file of last done receivers.
- doneReceivers.add(comp);
- }
+ ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();
+ for (int i=0; i<ris.size(); i++) {
+ ActivityInfo ai = ris.get(i).activityInfo;
+ ComponentName comp = new ComponentName(ai.packageName, ai.name);
+ if (lastDoneReceivers.contains(comp)) {
+ // We already did the pre boot receiver for this app with the current
+ // platform version, so don't do it again...
+ ris.remove(i);
+ i--;
+ // ...however, do keep it as one that has been done, so we don't
+ // forget about it when rewriting the file of last done receivers.
+ doneReceivers.add(comp);
}
}
@@ -11864,9 +11860,8 @@
return false;
}
- // If primary user, send broadcast to all available users, else just to userId
- final int[] users = userId == UserHandle.USER_OWNER ? getUsersLocked()
- : new int[] { userId };
+ // TODO: can we still do this with per user encryption?
+ final int[] users = getUsersLocked();
if (users.length <= 0) {
return false;
}
@@ -11917,7 +11912,7 @@
writeLastDonePreBootReceivers(doneReceivers);
systemReady(goingCallback);
}
- }, doneReceivers, UserHandle.USER_OWNER);
+ }, doneReceivers);
if (mWaitingUpdate) {
return;
@@ -17699,7 +17694,8 @@
kept = mainStack.ensureActivityConfigurationLocked(starting, changes, false);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
+ !PRESERVE_WINDOWS);
}
}
@@ -20170,7 +20166,7 @@
}
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
- if (userId != UserHandle.USER_OWNER) {
+ if (userId != UserHandle.USER_SYSTEM) {
Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
broadcastIntentLocked(null, null, intent, null,
@@ -20408,7 +20404,7 @@
for (int i = 0; i < num; i++) {
Integer oldUserId = mUserLru.get(i);
UserState oldUss = mStartedUsers.get(oldUserId);
- if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId
+ if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
|| oldUss.mState == UserState.STATE_STOPPING
|| oldUss.mState == UserState.STATE_SHUTDOWN) {
continue;
@@ -20493,8 +20489,12 @@
i++;
continue;
}
- if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId) {
- // Owner and current can't be stopped, but count as running.
+ if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
+ // Owner/System user and current user can't be stopped. We count it as running
+ // when it is not a pure system user.
+ if (UserInfo.isSystemOnly(oldUserId)) {
+ num--;
+ }
i++;
continue;
}
@@ -20517,8 +20517,8 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- if (userId < 0 || userId == UserHandle.USER_OWNER) {
- throw new IllegalArgumentException("Can't stop primary user " + userId);
+ if (userId < 0 || userId == UserHandle.USER_SYSTEM) {
+ throw new IllegalArgumentException("Can't stop system user " + userId);
}
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
synchronized (this) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b6d5d896..9809c2e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -30,6 +30,7 @@
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStackSupervisor.MOVING;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import android.graphics.Rect;
import android.util.ArraySet;
@@ -809,7 +810,7 @@
}
void goToSleep() {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Make sure any stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
@@ -1329,17 +1330,28 @@
return topHomeActivity == null || !topHomeActivity.isHomeActivity();
}
- if (focusedStackId == DOCKED_STACK_ID
- && stackIndex == (mStacks.indexOf(focusedStack) - 1)) {
+ final int belowFocusedIndex = mStacks.indexOf(focusedStack) - 1;
+ if (focusedStackId == DOCKED_STACK_ID && stackIndex == belowFocusedIndex) {
// Stacks directly behind the docked stack are always visible.
return true;
}
- if (mStackId == HOME_STACK_ID && focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
- // Home stack is always visible behind the fullscreen stack with a translucent activity.
- // This is done so that the home stack can act as a background to the translucent
- // activity.
- return hasTranslucentActivity(focusedStack);
+ if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && hasTranslucentActivity(focusedStack)) {
+ // Stacks behind the fullscreen stack with a translucent activity are always
+ // visible so they can act as a backdrop to the translucent activity.
+ // For example, dialog activities
+ if (stackIndex == belowFocusedIndex) {
+ return true;
+ }
+ if (belowFocusedIndex >= 0) {
+ final ActivityStack stack = mStacks.get(belowFocusedIndex);
+ if (stack.mStackId == DOCKED_STACK_ID && stackIndex == (belowFocusedIndex - 1)) {
+ // The stack behind the docked stack is also visible so we can have a complete
+ // backdrop to the translucent activity when the docked stack is up.
+ return true;
+ }
+ }
}
if (mStackId >= FIRST_STATIC_STACK_ID && mStackId <= LAST_STATIC_STACK_ID) {
@@ -1373,7 +1385,8 @@
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
*/
- final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
ActivityRecord top = topRunningActivityLocked(null);
if (top == null) {
return;
@@ -1422,7 +1435,7 @@
// First: if this is not the current activity being started, make
// sure it matches the current configuration.
if (r != starting) {
- ensureActivityConfigurationLocked(r, 0, false);
+ ensureActivityConfigurationLocked(r, 0, preserveWindows);
}
if (r.app == null || r.app.thread == null) {
@@ -2336,7 +2349,7 @@
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
mWindowManager.setAppVisibility(r.appToken, true);
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
@@ -4018,6 +4031,11 @@
return true;
}
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+ "Configuration changes for " + r + " ; taskChanges="
+ + Configuration.configurationDiffToString(taskChanges) + ", allChanges="
+ + Configuration.configurationDiffToString(changes));
+
// If the activity isn't currently running, just leave the new
// configuration and it will pick that up next time it starts.
if (r.app == null || r.app.thread == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7f7638b..17a4472 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -175,6 +175,9 @@
// should be created if it doesn't exist already.
private static final boolean CREATE_IF_NEEDED = true;
+ // Used to indicate that windows of activities should be preserved during the resize.
+ static final boolean PRESERVE_WINDOWS = true;
+
// Used to indicate if an object (e.g. task) should be moved/created
// at the top of its container (e.g. stack).
static final boolean ON_TOP = true;
@@ -189,6 +192,7 @@
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
+
static {
ACTION_TO_RUNTIME_PERMISSION.put(MediaStore.ACTION_IMAGE_CAPTURE,
Manifest.permission.CAMERA);
@@ -651,7 +655,7 @@
}
}
if (!didSomething) {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
@@ -1794,8 +1798,11 @@
return container.mStack;
}
- if (mFocusedStack != mHomeStack && (!newTask ||
- mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
+ // The fullscreen stack is the only stack that can contain any task regardless of if
+ // the task is resizeable or not. So, we let the task go in the fullscreen task if it
+ // is the focus stack.
+ if (mFocusedStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID
+ && (!newTask || mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
@@ -1814,7 +1821,7 @@
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
- int stackId = task != null ? task.getLaunchStackId() :
+ final int stackId = task != null ? task.getLaunchStackId() :
bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
FULLSCREEN_WORKSPACE_STACK_ID;
stack = getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
@@ -2620,7 +2627,7 @@
}
mLaunchingActivity.release();
}
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
// Atomically retrieve all of the other things to do.
@@ -2954,7 +2961,7 @@
}
}
- void resizeStackLocked(int stackId, Rect bounds) {
+ void resizeStackLocked(int stackId, Rect bounds, boolean preserveWindows) {
final ActivityStack stack = getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
@@ -2993,7 +3000,7 @@
// docked stack tasks to the fullscreen stack.
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
if (i != DOCKED_STACK_ID) {
- resizeStackLocked(i, null);
+ resizeStackLocked(i, null, preserveWindows);
}
}
@@ -3024,20 +3031,22 @@
tempRect.right -= leftChange;
tempRect.top -= bottomChange;
tempRect.bottom -= topChange;
- resizeStackLocked(i, tempRect);
+ resizeStackLocked(i, tempRect, PRESERVE_WINDOWS);
}
}
}
-
}
+ // Since we are resizing the stack, all other operations should strive to preserve
+ // windows.
+ preserveWindows = true;
}
stack.setBounds(bounds);
if (r != null) {
- final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, false);
+ final boolean updated = stack.ensureActivityConfigurationLocked(r, 0, preserveWindows);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- ensureActivitiesVisibleLocked(r, 0);
+ ensureActivitiesVisibleLocked(r, 0, preserveWindows);
if (!updated) {
resumeTopActivitiesLocked(stack, null, null);
}
@@ -3098,7 +3107,7 @@
final boolean preserveWindow = resizedByUser && !changedStacks;
kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
// All other activities must be made visible with their correct configuration.
- ensureActivitiesVisibleLocked(r, 0);
+ ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
if (!kept) {
resumeTopActivitiesLocked(stack, null, null);
if (changedStacks && stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
@@ -3201,7 +3210,13 @@
final boolean wasFocused = isFrontStack(task.stack) && (topRunningActivityLocked() == r);
final boolean wasResumed = wasFocused && (task.stack.mResumedActivity == r);
+ final boolean resizeable = task.mResizeable;
+ // Temporarily disable resizeablility of task we are moving. We don't want it to be resized
+ // if a docked stack is created below which will lead to the stack we are moving from and
+ // its resizeable tasks being resized.
+ task.mResizeable = false;
final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, toTop);
+ task.mResizeable = resizeable;
mWindowManager.moveTaskToStack(task.taskId, stack.mStackId, toTop);
if (task.stack != null) {
task.stack.removeTask(task, reason, MOVING);
@@ -3246,7 +3261,7 @@
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeTopActivitiesLocked();
}
@@ -3266,7 +3281,7 @@
stack.positionTask(task, position, stackChanged);
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
- stack.ensureActivitiesVisibleLocked(null, 0);
+ stack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeTopActivitiesLocked();
}
@@ -3441,7 +3456,7 @@
mService.updateUsageStats(r, true);
}
if (allResumedActivitiesComplete()) {
- ensureActivitiesVisibleLocked(null, 0);
+ ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
return true;
}
@@ -3527,14 +3542,15 @@
mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
}
- void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
final int topStackNdx = stacks.size() - 1;
for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges);
+ stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
}
}
}
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 424ceb1..c36fd06 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import java.io.File;
import java.io.FileInputStream;
@@ -347,7 +348,7 @@
stack.ensureActivityConfigurationLocked(starting, 0, false);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- stack.ensureActivitiesVisibleLocked(starting, 0);
+ stack.ensureActivitiesVisibleLocked(starting, 0, !PRESERVE_WINDOWS);
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 452378f..533f425 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -837,6 +837,7 @@
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFade();
}
if (target == Display.STATE_ON) {
@@ -910,6 +911,7 @@
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
+ mPowerState.dismissColorFade();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index d1bb8db..b3a0010 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -94,7 +94,7 @@
private void bindHardwareGeofence() {
mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
- mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER);
+ mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 04d382d..3974205 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2003,6 +2003,7 @@
case TYPE_SYSTEM_DIALOG:
case TYPE_VOLUME_OVERLAY:
case TYPE_PRIVATE_PRESENTATION:
+ case TYPE_DOCK_DIVIDER:
break;
}
@@ -2134,54 +2135,56 @@
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
+ case TYPE_DOCK_DIVIDER:
+ return 14;
case TYPE_KEYGUARD_SCRIM:
// the safety window that shows behind keyguard while keyguard is starting
- return 14;
- case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
- case TYPE_STATUS_BAR:
+ case TYPE_STATUS_BAR_SUB_PANEL:
return 16;
- case TYPE_STATUS_BAR_PANEL:
+ case TYPE_STATUS_BAR:
return 17;
- case TYPE_KEYGUARD_DIALOG:
+ case TYPE_STATUS_BAR_PANEL:
return 18;
+ case TYPE_KEYGUARD_DIALOG:
+ return 19;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 19;
+ return 20;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- return 20;
+ return 21;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
- return 21;
+ return 22;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
- return 22;
+ return 23;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
- return 23;
+ return 24;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
- return 24;
+ return 25;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
- return 25;
+ return 26;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
- return 26;
+ return 27;
case TYPE_ACCESSIBILITY_OVERLAY:
// overlay put by accessibility services to intercept user interaction
- return 27;
- case TYPE_SECURE_SYSTEM_OVERLAY:
return 28;
- case TYPE_BOOT_PROGRESS:
+ case TYPE_SECURE_SYSTEM_OVERLAY:
return 29;
+ case TYPE_BOOT_PROGRESS:
+ return 30;
case TYPE_POINTER:
// the (mouse) pointer layer
- return 30;
+ return 31;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
@@ -2271,6 +2274,7 @@
case TYPE_WALLPAPER:
case TYPE_DREAM:
case TYPE_KEYGUARD_SCRIM:
+ case TYPE_DOCK_DIVIDER:
return false;
default:
// Hide only windows below the keyguard host window.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 7ae3c79..c0dfbcb 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -129,7 +129,7 @@
intent.setComponent(keyguardComponent);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
- Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 87dc6c4..11a1639 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -305,9 +305,8 @@
throw new SecurityException("invalid status bar icon slot: " + slot);
}
- StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.OWNER, iconId,
- iconLevel, 0,
- contentDescription);
+ StatusBarIcon icon = new StatusBarIcon(iconPackage, UserHandle.SYSTEM, iconId,
+ iconLevel, 0, contentDescription);
//Slog.d(TAG, "setIcon slot=" + slot + " index=" + index + " icon=" + icon);
mIcons.setIcon(index, icon);
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index f4bd61f..6c5452a 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -188,7 +188,7 @@
| Context.BIND_AUTO_CREATE;
// Bind to Telecom and register the service
- if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) {
+ if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
mServiceConnection = serviceConnection;
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index cb0dba8..4392ab4 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.app.ActivityManager.HOME_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
@@ -111,6 +112,8 @@
/** Remove this display when animation on it has completed. */
boolean mDeferredRemoval;
+ final DockedStackDividerController mDividerControllerLocked;
+
/**
* @param display May not be null.
* @param service You know.
@@ -122,6 +125,7 @@
display.getMetrics(mDisplayMetrics);
isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
mService = service;
+ mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
}
int getDisplayId() {
@@ -552,4 +556,14 @@
public String toString() {
return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks;
}
+
+ TaskStack getDockedStack() {
+ for (int i = mStacks.size() - 1; i >= 0; i--) {
+ TaskStack stack = mStacks.get(i);
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ return stack;
+ }
+ }
+ return null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
new file mode 100644
index 0000000..ad207d4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package com.android.server.wm;
+
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+/**
+ * Controls showing and hiding of a docked stack divider on the display.
+ */
+public class DockedStackDividerController {
+ private static final String TAG = "DockedStackDivider";
+ private final Context mContext;
+ private final int mDividerWidth;
+ private final DisplayContent mDisplayContent;
+ private View mView;
+ private Rect mTmpRect = new Rect();
+
+ DockedStackDividerController(Context context, DisplayContent displayContent) {
+ mContext = context;
+ mDisplayContent = displayContent;
+ mDividerWidth = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ }
+
+ private void addDivider() {
+ View view = LayoutInflater.from(mContext).inflate(
+ com.android.internal.R.layout.docked_stack_divider, null);
+ WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ mDividerWidth, MATCH_PARENT, TYPE_DOCK_DIVIDER,
+ FLAG_TOUCHABLE_WHEN_WAKING | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
+ | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH,
+ PixelFormat.OPAQUE);
+ params.setTitle(TAG);
+ manager.addView(view, params, mDisplayContent.getDisplay(), null);
+ mView = view;
+ }
+
+ private void removeDivider() {
+ WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
+ manager.removeView(mView, true /* immediate */);
+ mView = null;
+ }
+
+ boolean hasDivider() {
+ return mView != null;
+ }
+
+ void update() {
+ TaskStack stack = mDisplayContent.getDockedStack();
+ if (stack != null && mView == null) {
+ addDivider();
+ } else if (stack == null && mView != null) {
+ removeDivider();
+ }
+ }
+
+ int getWidth() {
+ return mDividerWidth;
+ }
+
+
+ void positionDockedStackedDivider(Rect frame) {
+ TaskStack stack = mDisplayContent.getDockedStack();
+ if (stack == null) {
+ // Unfortunately we might end up with still having a divider, even though the underlying
+ // stack was already removed. This is because we are on AM thread and the removal of the
+ // divider was deferred to WM thread and hasn't happened yet.
+ return;
+ }
+ final @TaskStack.DockSide int side = stack.getDockSide();
+ stack.getBounds(mTmpRect);
+ switch (side) {
+ case TaskStack.DOCKED_LEFT:
+ frame.set(mTmpRect.right, frame.top, mTmpRect.right + frame.width(), frame.bottom);
+ break;
+ case TaskStack.DOCKED_TOP:
+ frame.set(frame.left, mTmpRect.bottom, mTmpRect.right,
+ mTmpRect.bottom + frame.height());
+ break;
+ case TaskStack.DOCKED_RIGHT:
+ frame.set(mTmpRect.left - frame.width(), frame.top, mTmpRect.left, frame.bottom);
+ break;
+ case TaskStack.DOCKED_BOTTOM:
+ frame.set(frame.left, mTmpRect.top - frame.height(), frame.right, mTmpRect.top);
+ break;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4541dd6..6ebff42 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
@@ -432,6 +433,10 @@
return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
}
+ boolean inDockedWorkspace() {
+ return mStack != null && mStack.mStackId == DOCKED_STACK_ID;
+ }
+
@Override
public boolean isFullscreen() {
return mFullscreen;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 1362555..96fcf93 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -352,7 +352,8 @@
// the docked stack occupies a dedicated region on screen.
bounds = new Rect();
displayContent.getLogicalDisplayRect(mTmpRect);
- getInitialDockedStackBounds(mTmpRect, bounds, mStackId);
+ getInitialDockedStackBounds(mTmpRect, bounds, mStackId,
+ mDisplayContent.mDividerControllerLocked.getWidth() / 2);
}
updateDisplayInfo(bounds);
@@ -371,27 +372,29 @@
* @param displayRect The bounds of the display the docked stack is on.
* @param outBounds Output bounds that should be used for the stack.
* @param stackId Id of stack we are calculating the bounds for.
+ * @param adjustment
*/
- private static void getInitialDockedStackBounds(
- Rect displayRect, Rect outBounds, int stackId) {
+ private static void getInitialDockedStackBounds(Rect displayRect, Rect outBounds, int stackId,
+ int adjustment) {
// Docked stack start off occupying half the screen space.
+ final boolean dockedStack = stackId == DOCKED_STACK_ID;
final boolean splitHorizontally = displayRect.width() > displayRect.height();
final boolean topOrLeftCreateMode =
WindowManagerService.sDockedStackCreateMode == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
- final boolean placeTopOrLeft = (stackId == DOCKED_STACK_ID && topOrLeftCreateMode)
- || (stackId != DOCKED_STACK_ID && !topOrLeftCreateMode);
+ final boolean placeTopOrLeft = (dockedStack && topOrLeftCreateMode)
+ || (!dockedStack && !topOrLeftCreateMode);
outBounds.set(displayRect);
if (placeTopOrLeft) {
if (splitHorizontally) {
- outBounds.right = displayRect.centerX();
+ outBounds.right = displayRect.centerX() - adjustment;
} else {
- outBounds.bottom = displayRect.centerY();
+ outBounds.bottom = displayRect.centerY() - adjustment;
}
} else {
if (splitHorizontally) {
- outBounds.left = displayRect.centerX();
+ outBounds.left = displayRect.centerX() + adjustment;
} else {
- outBounds.top = displayRect.centerY();
+ outBounds.top = displayRect.centerY() + adjustment;
}
}
}
@@ -404,7 +407,8 @@
private void resizeNonDockedStacks(boolean fullscreen) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
if (!fullscreen) {
- getInitialDockedStackBounds(mTmpRect, mTmpRect, FULLSCREEN_WORKSPACE_STACK_ID);
+ getInitialDockedStackBounds(mTmpRect, mTmpRect, FULLSCREEN_WORKSPACE_STACK_ID,
+ mDisplayContent.mDividerControllerLocked.getWidth());
}
final int count = mService.mStackIdToStack.size();
@@ -546,14 +550,14 @@
final int orientation = mService.mCurConfiguration.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Portrait mode, docked either at the top or the bottom.
- if (mTmpRect.top - mBounds.top < mTmpRect.bottom - mBounds.bottom) {
+ if (mBounds.top - mTmpRect.top < mTmpRect.bottom - mBounds.bottom) {
return DOCKED_TOP;
} else {
return DOCKED_BOTTOM;
}
} else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Landscape mode, docked either on the left or on the right.
- if (mTmpRect.left - mBounds.left < mTmpRect.right - mBounds.right) {
+ if (mBounds.left - mTmpRect.left < mTmpRect.right - mBounds.right) {
return DOCKED_LEFT;
} else {
return DOCKED_RIGHT;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 29598ab..d510c4a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.DOCKED_STACK_ID;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -33,6 +34,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -921,6 +923,7 @@
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
+
LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
@@ -1854,6 +1857,11 @@
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
+ } else if (type == TYPE_DOCK_DIVIDER) {
+ if (displayContent.mDividerControllerLocked.hasDivider()) {
+ Slog.w(TAG, "Attempted to add docked stack divider twice. Aborting.");
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+ }
} else if (token.appWindowToken != null) {
Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
// It is not valid to use an app token with other system types; we will
@@ -4521,7 +4529,10 @@
}
stack.attachDisplayContent(displayContent);
displayContent.attachStack(stack, onTop);
-
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER,
+ displayContent).sendToTarget();
+ }
moveStackWindowsLocked(displayContent);
final WindowList windows = displayContent.getWindowList();
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
@@ -4544,6 +4555,11 @@
void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
displayContent.detachStack(stack);
stack.detachDisplay();
+ // We can't directly remove the divider, because only the WM thread can do these operations
+ // and we can be on AM thread.
+ if (stack.mStackId == DOCKED_STACK_ID) {
+ mH.obtainMessage(H.UPDATE_DOCKED_STACK_DIVIDER, displayContent).sendToTarget();
+ }
}
public void detachStack(int stackId) {
@@ -7220,6 +7236,8 @@
public static final int TAP_DOWN_OUTSIDE_TASK = 40;
public static final int FINISH_TASK_POSITIONING = 41;
+ public static final int UPDATE_DOCKED_STACK_DIVIDER = 42;
+
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
@@ -7759,6 +7777,13 @@
}
}
break;
+ case UPDATE_DOCKED_STACK_DIVIDER: {
+ DisplayContent content = (DisplayContent) msg.obj;
+ synchronized (mWindowMap) {
+ content.mDividerControllerLocked.update();
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a6478a0..64440d3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -707,6 +708,8 @@
mContentFrame.set(mFrame);
mVisibleFrame.set(mContentFrame);
mStableFrame.set(mContentFrame);
+ } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
+ mDisplayContent.mDividerControllerLocked.positionDockedStackedDivider(mFrame);
} else {
mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
Math.max(mContentFrame.top, mFrame.top),
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e11e317..b0a04c7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1226,7 +1226,7 @@
void removeUserData(int userHandle) {
synchronized (this) {
- if (userHandle == UserHandle.USER_OWNER) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
}
@@ -1372,12 +1372,12 @@
&& !hasUserSetupCompleted(userId);
if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
- if ((userId == UserHandle.USER_OWNER && (ownsDevice || ownsInitialization))
+ if ((userId == UserHandle.USER_SYSTEM && (ownsDevice || ownsInitialization))
|| (ownsDevice && ownsProfile)) {
return true;
}
} else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
- if ((userId == UserHandle.USER_OWNER && ownsDevice) || ownsProfile
+ if ((userId == UserHandle.USER_SYSTEM && ownsDevice) || ownsProfile
|| ownsInitialization) {
return true;
}
@@ -1892,7 +1892,7 @@
}
private void onLockSettingsReady() {
- getUserData(UserHandle.USER_OWNER);
+ getUserData(UserHandle.USER_SYSTEM);
loadOwners();
cleanUpOldUsers();
// Register an observer for watching for user setup complete.
@@ -3107,10 +3107,10 @@
private void setDoNotAskCredentialsOnBoot() {
synchronized (this) {
- DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
if (!policyData.doNotAskCredentialsOnBoot) {
policyData.doNotAskCredentialsOnBoot = true;
- saveSettingsLocked(UserHandle.USER_OWNER);
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
}
}
}
@@ -3120,7 +3120,7 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
synchronized (this) {
- DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
return policyData.doNotAskCredentialsOnBoot;
}
}
@@ -3475,20 +3475,14 @@
final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
- final String source;
- final ComponentName cname = admin.info.getComponent();
- if (cname != null) {
- source = cname.flattenToShortString();
- } else {
- source = admin.info.getPackageName();
- }
+ final String source = admin.info.getComponent().flattenToShortString();
long ident = binderClearCallingIdentity();
try {
if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
&& !hasUserSetupCompleted(userHandle);
- if (userHandle != UserHandle.USER_OWNER
+ if (userHandle != UserHandle.USER_SYSTEM
|| !(isDeviceOwner(admin.info.getPackageName())
|| ownsInitialization)) {
throw new SecurityException(
@@ -3510,7 +3504,7 @@
}
private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle, String reason) {
- if (userHandle == UserHandle.USER_OWNER) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
wipeDataLocked(wipeExtRequested, reason);
} else {
mHandler.post(new Runnable() {
@@ -3519,7 +3513,7 @@
try {
IActivityManager am = getIActivityManager();
if (am.getCurrentUser().id == userHandle) {
- am.switchUser(UserHandle.USER_OWNER);
+ am.switchUser(UserHandle.USER_SYSTEM);
}
boolean isManagedProfile = isManagedProfile(userHandle);
@@ -3733,8 +3727,8 @@
synchronized(this) {
Preconditions.checkNotNull(who, "ComponentName is null");
- // Only check if owner has set global proxy. We don't allow other users to set it.
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ // Only check if system user has set global proxy. We don't allow other users to set it.
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
@@ -3750,8 +3744,8 @@
}
}
- // If the user is not the owner, don't set the global proxy. Fail silently.
- if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ // If the user is not system, don't set the global proxy. Fail silently.
+ if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User "
+ UserHandle.getCallingUserId() + " is not permitted.");
return null;
@@ -3786,7 +3780,7 @@
}
enforceCrossUserPermission(userHandle);
synchronized(this) {
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// Scan through active admins and find if anyone has already
// set the global proxy.
final int N = policy.mAdminList.size();
@@ -3874,10 +3868,9 @@
final int userHandle = UserHandle.getCallingUserId();
synchronized (this) {
// Check for permissions
- // Only owner can set storage encryption
- if (userHandle != UserHandle.USER_OWNER
- || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only owner is allowed to set storage encryption. User "
+ // Only system user can set storage encryption
+ if (userHandle != UserHandle.USER_SYSTEM) {
+ Slog.w(LOG_TAG, "Only owner/system user is allowed to set storage encryption. User "
+ UserHandle.getCallingUserId() + " is not permitted.");
return 0;
}
@@ -3896,7 +3889,7 @@
saveSettingsLocked(userHandle);
}
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// (2) Compute "max" for all admins
boolean newRequested = false;
final int N = policy.mAdminList.size();
@@ -4259,7 +4252,7 @@
try {
IBackupManager ibm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
- ibm.setBackupServiceActive(UserHandle.USER_OWNER, false);
+ ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
} catch (RemoteException e) {
throw new IllegalStateException("Failed deactivating backup service.", e);
} finally {
@@ -4314,7 +4307,7 @@
return null;
}
String deviceOwnerPackage = mOwners.getDeviceOwnerPackageName();
- return getApplicationLabel(deviceOwnerPackage, UserHandle.USER_OWNER);
+ return getApplicationLabel(deviceOwnerPackage, UserHandle.USER_SYSTEM);
}
}
@@ -4325,7 +4318,7 @@
return null;
}
- DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
final int n = policy.mAdminList.size();
for (int i = 0; i < n; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
@@ -4351,7 +4344,7 @@
throw new SecurityException("clearDeviceOwner can only be called by the device owner");
}
synchronized (this) {
- clearUserPoliciesLocked(new UserHandle(UserHandle.USER_OWNER));
+ clearUserPoliciesLocked(new UserHandle(UserHandle.USER_SYSTEM));
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
@@ -4361,7 +4354,7 @@
try {
IBackupManager ibm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
- ibm.setBackupServiceActive(UserHandle.USER_OWNER, true);
+ ibm.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
} catch (RemoteException e) {
throw new IllegalStateException("Failed reactivating backup service.", e);
} finally {
@@ -4611,7 +4604,7 @@
removeActiveAdmin(who, userId);
}
- if (userId == UserHandle.USER_OWNER) {
+ if (userId == UserHandle.USER_SYSTEM) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
}
@@ -4794,7 +4787,7 @@
int callingUid = binderGetCallingUid();
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
- if (!hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ if (!hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
return;
}
// STOPSHIP Do proper check in split user mode
@@ -4818,7 +4811,7 @@
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
// STOPSHIP Do proper check in split user mode
if (!UserManager.isSplitSystemUser()) {
- if (hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
throw new IllegalStateException("Cannot set the device owner if the device is "
+ "already set-up");
}
@@ -5526,7 +5519,7 @@
long id = binderClearCallingIdentity();
try {
- int userId = UserHandle.USER_OWNER;
+ int userId = UserHandle.USER_SYSTEM;
if (userHandle != null) {
userId = userHandle.getIdentifier();
}
@@ -5563,13 +5556,13 @@
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabled) {
Preconditions.checkNotNull(who, "ComponentName is null");
- final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
- final int userHandle = user.getIdentifier();
+ final int userHandle = UserHandle.getCallingUserId();
+ final UserHandle user = new UserHandle(userHandle);
synchronized (this) {
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
- if (!isDeviceOwner && userHandle != UserHandle.USER_OWNER
+ if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
throw new SecurityException("Profile owners cannot set user restriction " + key);
}
@@ -5594,8 +5587,7 @@
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
iAudioService.setMasterMute(true, 0, mContext.getPackageName(),
userHandle);
- }
- if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
+ } else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
userHandle);
@@ -5607,8 +5599,9 @@
Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
userHandle);
} else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
- // Only disable adb if changing for primary user, since it is global
- if (userHandle == UserHandle.USER_OWNER) {
+ // Only disable adb if changing for system user, since it is global
+ // TODO: should this be admin user?
+ if (userHandle == UserHandle.USER_SYSTEM) {
Settings.Global.putStringForUser(mContext.getContentResolver(),
Settings.Global.ADB_ENABLED, "0", userHandle);
}
@@ -6497,8 +6490,8 @@
mContext.enforceCallingOrSelfPermission(permission.NOTIFY_PENDING_SYSTEM_UPDATE,
"Only the system update service can broadcast update information");
- if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only the system update service in the primary user " +
+ if (UserHandle.getCallingUserId() != UserHandle.USER_SYSTEM) {
+ Slog.w(LOG_TAG, "Only the system update service in the system user " +
"can broadcast update information.");
return;
}
diff --git a/core/java/android/net/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
similarity index 99%
rename from core/java/android/net/IpReachabilityMonitor.java
rename to services/net/java/android/net/ip/IpReachabilityMonitor.java
index 2283004c..3acd565 100644
--- a/core/java/android/net/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net;
+package android.net.ip;
import com.android.internal.annotations.GuardedBy;
diff --git a/core/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java
similarity index 100%
rename from core/java/android/net/netlink/NetlinkConstants.java
rename to services/net/java/android/net/netlink/NetlinkConstants.java
diff --git a/core/java/android/net/netlink/NetlinkErrorMessage.java b/services/net/java/android/net/netlink/NetlinkErrorMessage.java
similarity index 100%
rename from core/java/android/net/netlink/NetlinkErrorMessage.java
rename to services/net/java/android/net/netlink/NetlinkErrorMessage.java
diff --git a/core/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java
similarity index 100%
rename from core/java/android/net/netlink/NetlinkMessage.java
rename to services/net/java/android/net/netlink/NetlinkMessage.java
diff --git a/core/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
similarity index 100%
rename from core/java/android/net/netlink/NetlinkSocket.java
rename to services/net/java/android/net/netlink/NetlinkSocket.java
diff --git a/core/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
similarity index 100%
rename from core/java/android/net/netlink/RtNetlinkNeighborMessage.java
rename to services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
diff --git a/core/java/android/net/netlink/StructNdMsg.java b/services/net/java/android/net/netlink/StructNdMsg.java
similarity index 100%
rename from core/java/android/net/netlink/StructNdMsg.java
rename to services/net/java/android/net/netlink/StructNdMsg.java
diff --git a/core/java/android/net/netlink/StructNdaCacheInfo.java b/services/net/java/android/net/netlink/StructNdaCacheInfo.java
similarity index 100%
rename from core/java/android/net/netlink/StructNdaCacheInfo.java
rename to services/net/java/android/net/netlink/StructNdaCacheInfo.java
diff --git a/core/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
similarity index 100%
rename from core/java/android/net/netlink/StructNlAttr.java
rename to services/net/java/android/net/netlink/StructNlAttr.java
diff --git a/core/java/android/net/netlink/StructNlMsgErr.java b/services/net/java/android/net/netlink/StructNlMsgErr.java
similarity index 100%
rename from core/java/android/net/netlink/StructNlMsgErr.java
rename to services/net/java/android/net/netlink/StructNlMsgErr.java
diff --git a/core/java/android/net/netlink/StructNlMsgHdr.java b/services/net/java/android/net/netlink/StructNlMsgHdr.java
similarity index 100%
rename from core/java/android/net/netlink/StructNlMsgHdr.java
rename to services/net/java/android/net/netlink/StructNlMsgHdr.java
diff --git a/core/tests/coretests/src/android/net/netlink/NetlinkErrorMessageTest.java b/services/tests/servicestests/src/android/net/netlink/NetlinkErrorMessageTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/netlink/NetlinkErrorMessageTest.java
rename to services/tests/servicestests/src/android/net/netlink/NetlinkErrorMessageTest.java
diff --git a/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java b/services/tests/servicestests/src/android/net/netlink/NetlinkSocketTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java
rename to services/tests/servicestests/src/android/net/netlink/NetlinkSocketTest.java
diff --git a/core/tests/coretests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/services/tests/servicestests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
rename to services/tests/servicestests/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 2cf42f0..154cbd3 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -517,7 +517,7 @@
com.android.internal.R.bool.config_disableUsbPermissionDialogs);
synchronized (mLock) {
- if (UserHandle.OWNER.equals(user)) {
+ if (UserHandle.SYSTEM.equals(user)) {
upgradeSingleUserLocked();
}
readSettingsLocked();
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 5fbfe8a..ceb3993e 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -57,6 +57,7 @@
import android.content.res.Configuration;
import android.util.Log;
+
public class ActivityTestMain extends Activity {
static final String TAG = "ActivityTest";
@@ -315,7 +316,7 @@
Log.i(TAG, "Service disconnected " + name);
}
};
- if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ if (bindServiceAsUser(intent, conn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
mConnections.add(conn);
} else {
Toast.makeText(ActivityTestMain.this, "Failed to bind",
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 163fbcb..3b7bf85 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -48,9 +48,6 @@
import java.io.InputStream;
import java.util.Iterator;
-/**
- *
- */
public final class BridgeResources extends Resources {
private BridgeContext mContext;
@@ -278,7 +275,7 @@
* always Strings. The ideal signature for the method should be <T super String>, but java
* generics don't support it.
*/
- private <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
+ <T extends CharSequence> T[] fillValues(ArrayResourceValue resValue, T[] values) {
int i = 0;
for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
@SuppressWarnings("unchecked")
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 6a61090..31dd3d9 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -16,6 +16,7 @@
package android.content.res;
+import com.android.ide.common.rendering.api.ArrayResourceValue;
import com.android.ide.common.rendering.api.AttrResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources;
@@ -33,6 +34,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.Nullable;
+import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
@@ -740,12 +742,20 @@
*/
@Override
public CharSequence[] getTextArray(int index) {
- String value = getString(index);
- if (value != null) {
- return new CharSequence[] { value };
+ if (!hasValue(index)) {
+ return null;
}
-
- return null;
+ ResourceValue resVal = mResourceData[index];
+ if (resVal instanceof ArrayResourceValue) {
+ ArrayResourceValue array = (ArrayResourceValue) resVal;
+ int count = array.getElementCount();
+ return count >= 0 ? mBridgeResources.fillValues(array, new CharSequence[count]) : null;
+ }
+ int id = getResourceId(index, 0);
+ String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
+ throw new NotFoundException(
+ String.format("%1$s in %2$s%3$s is not a valid array resource.",
+ resVal.getValue(), mNames[index], resIdMessage));
}
@Override
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0d95b38..23be8e0 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -23,6 +23,7 @@
import android.net.wifi.ScanSettings;
import android.net.wifi.WifiChannel;
import android.net.wifi.ScanResult;
+import android.net.wifi.ScanInfo;
import android.net.wifi.WifiConnectionStatistics;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.Network;
@@ -70,6 +71,10 @@
void disconnect();
+ List<ScanInfo> getScanInfos(String callingPackage);
+
+ void setOsuSelection(int osuID);
+
void reconnect();
void reassociate();
diff --git a/wifi/java/android/net/wifi/ScanInfo.aidl b/wifi/java/android/net/wifi/ScanInfo.aidl
new file mode 100644
index 0000000..18ae508
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2015, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable ScanInfo;
diff --git a/wifi/java/android/net/wifi/ScanInfo.java b/wifi/java/android/net/wifi/ScanInfo.java
new file mode 100644
index 0000000..39186fa
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanInfo.java
@@ -0,0 +1,189 @@
+package android.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class ScanInfo implements Parcelable {
+ private final ScanResult mScanResult;
+
+ private final long mBSSID; // The BSSID of the best AP with an SSID matching the OSU
+ private final int mRSSI; // RSSI of the AP with BSSID
+ private final String mSSID; // The SSID to connect to for an OSU connection.
+ private final String mName;
+ private final String mServiceDescription;
+ private final String mIconType;
+ private final byte[] mIconData;
+ private final int mOSUIdentity;
+
+ public ScanInfo(ScanResult scanResult) {
+ mScanResult = scanResult;
+
+ mBSSID = -1;
+ mRSSI = -1;
+ mSSID = null;
+ mName = null;
+ mServiceDescription = null;
+ mIconType = null;
+ mIconData = null;
+ mOSUIdentity = -1;
+ }
+
+ public ScanInfo(long BSSID, int rssi, String SSID, String name, String serviceDescription,
+ String iconType, byte[] iconData, int OSUIdentity) {
+ mBSSID = BSSID;
+ mRSSI = rssi;
+ mSSID = SSID;
+ mName = name;
+ mServiceDescription = serviceDescription;
+ mIconType = iconType;
+ mIconData = iconData;
+ mOSUIdentity = OSUIdentity;
+
+ mScanResult = null;
+ }
+
+ /**
+ * Get the scan result of this ScanInfo.
+ * @return The ScanResult, if this ScanInfo contains a one. If the ScanInfo contains
+ * OSU information getScanResult will return null.
+ */
+ public ScanResult getScanResult() {
+ return mScanResult;
+ }
+
+ /**
+ * OSU only: The BSSID of the AP who advertises the OSU SSID. This value is not guaranteed to
+ * be correct; In the somewhat unlikely case that multiple APs advertise OSU SSIDs that matches
+ * an OSU information element returned through ANQP and one of those is not related to an OSU
+ * there is a (slight) risk that the BSSID is for a "spoof" OSU.
+ * The matching algorithm that produces the ScanInfo objects makes a best effort to get the
+ * matching right though and since it is (a) fair to assume that the OSU SSID resides on the
+ * same AP as the one advertising the OSU information, and (b) BSSIDs for multi-SSID APs are
+ * typically adjacent to each other, matching will prefer the BSSID closest to the advertising
+ * APs BSSID if multiple SSIDs match.
+ * @return The BSSID.
+ */
+ public long getBssid() {
+ return mBSSID;
+ }
+
+ /**
+ * OSU only.
+ * @return The signal level of the AP associated with the BSSID from getBSSID.
+ */
+ public int getRssi() {
+ return mRSSI;
+ }
+
+ /**
+ * OSU only.
+ * @return The SSID of the AP to which to associate to establish an OSU connection.
+ */
+ public String getSsid() {
+ return mSSID;
+ }
+
+ /**
+ * OSU only.
+ * @return The name of the Service Provider of the OSU.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * OSU only.
+ * @return The service description of the OSU.
+ */
+ public String getServiceDescription() {
+ return mServiceDescription;
+ }
+
+ /**
+ * OSU only.
+ * Get the type of icon that icon data represents, e.g. JPG, PNG etc. This field is formatted
+ * using standard MIME encodings per RFC-4288 and IANA MIME media types.
+ * @return The icon type in icon data.
+ */
+ public String getIconType() {
+ return mIconType;
+ }
+
+ /**
+ * OSU only.
+ * @return The binary data of the icon.
+ */
+ public byte[] getIconData() {
+ return mIconData;
+ }
+
+ /**
+ * OSU only.
+ * @return a unique identity for the OSU. This value is generated by the framework and should
+ * be used to uniquely identify a specific OSU. Please note that values may be reused after
+ * a very long time-span (in any normal scenario, likely years) and implementations should make
+ * sure to not rely on any long term persisted values.
+ */
+ public int getOsuIdentity() {
+ return mOSUIdentity;
+ }
+
+ private static final int ScanResultMarker = 0;
+ private static final int OSUMarker = 1;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface {@hide} */
+ public static final Creator<ScanInfo> CREATOR =
+ new Creator<ScanInfo>() {
+ @Override
+ public ScanInfo createFromParcel(Parcel source) {
+ int marker = source.readInt();
+ if (marker == ScanResultMarker) {
+ return new ScanInfo(ScanResult.CREATOR.createFromParcel(source));
+ }
+ else if (marker == OSUMarker) {
+ return new ScanInfo(
+ source.readLong(),
+ source.readInt(),
+ source.readString(),
+ source.readString(),
+ source.readString(),
+ source.readString(),
+ source.createByteArray(),
+ source.readInt()
+ );
+ }
+ else {
+ throw new RuntimeException("Bad ScanInfo data");
+ }
+ }
+
+ @Override
+ public ScanInfo[] newArray(int size) {
+ return new ScanInfo[0];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mScanResult != null) {
+ dest.writeInt(ScanResultMarker);
+ mScanResult.writeToParcel(dest, flags);
+ return;
+ }
+
+ dest.writeInt(OSUMarker);
+ dest.writeLong(mBSSID);
+ dest.writeInt(mRSSI);
+ dest.writeString(mSSID);
+ dest.writeString(mName);
+ dest.writeString(mServiceDescription);
+ dest.writeString(mIconType);
+ dest.writeByteArray(mIconData);
+ dest.writeInt(mOSUIdentity);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cf88df4..ff8d6d4d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1315,6 +1315,30 @@
}
/**
+ * An augmented version of getScanResults that returns ScanResults as well as OSU information
+ * wrapped in ScanInfo objects.
+ * @return
+ */
+ public List<ScanInfo> getScanInfos() {
+ try {
+ return mService.getScanInfos(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Notify the OSU framework about the currently selected OSU.
+ * @param osuID The OSU ID from ScanInfo.getOsuIdentity()
+ */
+ public void setOsuSelection(int osuID) {
+ try {
+ mService.setOsuSelection(osuID);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Check if scanning is always available.
*
* If this return {@code true}, apps can issue {@link #startScan} and fetch scan results