Merge "Fix FLAG_ACTIVITY_CLEAR_TOP not working for aliased activities"
diff --git a/api/current.txt b/api/current.txt
index 2fd32c5..c7f0a75 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5705,6 +5705,7 @@
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
+ method public boolean isWallpaperSettingAllowed();
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6328,6 +6329,7 @@
method public long getRxPackets();
method public long getStartTimeStamp();
method public int getState();
+ method public int getTag();
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
@@ -6337,6 +6339,8 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
+ field public static final int TAG_ALL = 0; // 0x0
+ field public static final int TAG_ANY = -1; // 0xffffffff
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6345,9 +6349,12 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
}
public final class UsageEvents implements android.os.Parcelable {
@@ -28529,6 +28536,7 @@
field public static java.lang.String DIRECTORY_DCIM;
field public static java.lang.String DIRECTORY_DOCUMENTS;
field public static java.lang.String DIRECTORY_DOWNLOADS;
+ field public static java.lang.String DIRECTORY_HOME;
field public static java.lang.String DIRECTORY_MOVIES;
field public static java.lang.String DIRECTORY_MUSIC;
field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -29264,6 +29272,7 @@
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+ field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_SMS = "no_sms";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -34348,6 +34357,7 @@
package android.service.notification {
public class Condition implements android.os.Parcelable {
+ ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
method public android.service.notification.Condition copy();
method public int describeContents();
@@ -34379,7 +34389,6 @@
method public final void notifyConditions(android.service.notification.Condition...);
method public android.os.IBinder onBind(android.content.Intent);
method public abstract void onConnected();
- method public abstract void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -43245,7 +43254,7 @@
method public abstract void setNavigationBarColor(int);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
- method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+ method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
method public void setReturnTransition(android.transition.Transition);
method public void setSharedElementEnterTransition(android.transition.Transition);
method public void setSharedElementExitTransition(android.transition.Transition);
@@ -43332,7 +43341,7 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
- public static abstract interface Window.RestrictedCaptionAreaListener {
+ public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/api/removed.txt b/api/removed.txt
index 2c6729d..0bf6594 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -199,6 +199,14 @@
}
+package android.service.notification {
+
+ public abstract class ConditionProviderService extends android.app.Service {
+ method public void onRequestConditions(int);
+ }
+
+}
+
package android.test.mock {
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index 5b640cd..3c5e59e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5838,6 +5838,7 @@
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
+ method public boolean isWallpaperSettingAllowed();
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6585,6 +6586,7 @@
method public long getRxPackets();
method public long getStartTimeStamp();
method public int getState();
+ method public int getTag();
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
@@ -6594,6 +6596,8 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
+ field public static final int TAG_ALL = 0; // 0x0
+ field public static final int TAG_ANY = -1; // 0xffffffff
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6602,9 +6606,12 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
}
public final class UsageEvents implements android.os.Parcelable {
@@ -30556,6 +30563,7 @@
field public static java.lang.String DIRECTORY_DCIM;
field public static java.lang.String DIRECTORY_DOCUMENTS;
field public static java.lang.String DIRECTORY_DOWNLOADS;
+ field public static java.lang.String DIRECTORY_HOME;
field public static java.lang.String DIRECTORY_MOVIES;
field public static java.lang.String DIRECTORY_MUSIC;
field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -31310,6 +31318,7 @@
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+ field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_SMS = "no_sms";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -36528,6 +36537,7 @@
package android.service.notification {
public class Condition implements android.os.Parcelable {
+ ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
method public android.service.notification.Condition copy();
method public int describeContents();
@@ -36559,7 +36569,7 @@
method public final void notifyConditions(android.service.notification.Condition...);
method public android.os.IBinder onBind(android.content.Intent);
method public abstract void onConnected();
- method public abstract void onRequestConditions(int);
+ method public void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -45663,7 +45673,7 @@
method public abstract void setNavigationBarColor(int);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
- method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+ method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
method public void setReturnTransition(android.transition.Transition);
method public void setSharedElementEnterTransition(android.transition.Transition);
method public void setSharedElementExitTransition(android.transition.Transition);
@@ -45750,7 +45760,7 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
- public static abstract interface Window.RestrictedCaptionAreaListener {
+ public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 47eec48..3e755ae 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5707,6 +5707,7 @@
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
+ method public boolean isWallpaperSettingAllowed();
method public boolean isWallpaperSupported();
method public android.graphics.drawable.Drawable peekDrawable();
method public android.graphics.drawable.Drawable peekFastDrawable();
@@ -6330,6 +6331,7 @@
method public long getRxPackets();
method public long getStartTimeStamp();
method public int getState();
+ method public int getTag();
method public long getTxBytes();
method public long getTxPackets();
method public int getUid();
@@ -6339,6 +6341,8 @@
field public static final int STATE_ALL = -1; // 0xffffffff
field public static final int STATE_DEFAULT = 1; // 0x1
field public static final int STATE_FOREGROUND = 2; // 0x2
+ field public static final int TAG_ALL = 0; // 0x0
+ field public static final int TAG_ANY = -1; // 0xffffffff
field public static final int UID_ALL = -1; // 0xffffffff
field public static final int UID_REMOVED = -4; // 0xfffffffc
field public static final int UID_TETHERING = -5; // 0xfffffffb
@@ -6347,9 +6351,12 @@
public class NetworkStatsManager {
method public android.app.usage.NetworkStats queryDetails(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats queryDetailsForUid(int, java.lang.String, long, long, int) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats queryDetailsForUidTag(int, java.lang.String, long, long, int, int) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats querySummary(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, java.lang.String, long, long, boolean) throws android.os.RemoteException, java.lang.SecurityException;
}
public final class UsageEvents implements android.os.Parcelable {
@@ -28538,6 +28545,7 @@
field public static java.lang.String DIRECTORY_DCIM;
field public static java.lang.String DIRECTORY_DOCUMENTS;
field public static java.lang.String DIRECTORY_DOWNLOADS;
+ field public static java.lang.String DIRECTORY_HOME;
field public static java.lang.String DIRECTORY_MOVIES;
field public static java.lang.String DIRECTORY_MUSIC;
field public static java.lang.String DIRECTORY_NOTIFICATIONS;
@@ -29274,6 +29282,7 @@
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SAFE_BOOT = "no_safe_boot";
field public static final java.lang.String DISALLOW_SET_USER_ICON = "no_set_user_icon";
+ field public static final java.lang.String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_SMS = "no_sms";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
@@ -34363,6 +34372,7 @@
package android.service.notification {
public class Condition implements android.os.Parcelable {
+ ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int);
ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
method public android.service.notification.Condition copy();
method public int describeContents();
@@ -34394,7 +34404,6 @@
method public final void notifyConditions(android.service.notification.Condition...);
method public android.os.IBinder onBind(android.content.Intent);
method public abstract void onConnected();
- method public abstract void onRequestConditions(int);
method public abstract void onSubscribe(android.net.Uri);
method public abstract void onUnsubscribe(android.net.Uri);
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
@@ -43262,7 +43271,7 @@
method public abstract void setNavigationBarColor(int);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
- method public final void setRestrictedCaptionAreaListener(android.view.Window.RestrictedCaptionAreaListener);
+ method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
method public void setReturnTransition(android.transition.Transition);
method public void setSharedElementEnterTransition(android.transition.Transition);
method public void setSharedElementExitTransition(android.transition.Transition);
@@ -43349,7 +43358,7 @@
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
}
- public static abstract interface Window.RestrictedCaptionAreaListener {
+ public static abstract interface Window.OnRestrictedCaptionAreaChangedListener {
method public abstract void onRestrictedCaptionAreaChanged(android.graphics.Rect);
}
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 2c6729d..0bf6594 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -199,6 +199,14 @@
}
+package android.service.notification {
+
+ public abstract class ConditionProviderService extends android.app.Service {
+ method public void onRequestConditions(int);
+ }
+
+}
+
package android.test.mock {
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 82170d1..cb29419 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -560,11 +560,13 @@
}
/**
- * Returns true if the windows of tasks being moved to this stack should be preserved so
- * there isn't a display gap.
+ * Returns true if the windows of tasks being moved to the target stack from the source
+ * stack should be replaced, meaning that window manager will keep the old window around
+ * until the new is ready.
*/
- public static boolean preserveWindowOnTaskMove(int stackId) {
- return stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
+ public static boolean replaceWindowsOnTaskMove(int sourceStackId, int targetStackId) {
+ return sourceStackId == FREEFORM_WORKSPACE_STACK_ID
+ || targetStackId == FREEFORM_WORKSPACE_STACK_ID;
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 56e4afa..b5b2753 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5080,6 +5080,10 @@
}
}
+ // Add the lib dir path to hardware renderer so that vulkan layers
+ // can be searched for within that directory.
+ ThreadedRenderer.setLibDir(data.info.getLibDir());
+
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index fa0fbd1..04493cb 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -113,4 +113,9 @@
* Check whether wallpapers are supported for the calling user.
*/
boolean isWallpaperSupported(in String callingPackage);
+
+ /**
+ * Check whether setting of wallpapers are allowed for the calling user.
+ */
+ boolean isWallpaperSettingAllowed(in String callingPackage);
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index b0ffd21..eda82c0 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -74,7 +74,8 @@
* {@link #getInstance(android.content.Context) getInstance()}.
*
* <p> An app can check whether wallpapers are supported for the current user, by calling
- * {@link #isWallpaperSupported()}.
+ * {@link #isWallpaperSupported()}, and whether setting of wallpapers is allowed, by calling
+ * {@link #isWallpaperSettingAllowed()}.
*/
public class WallpaperManager {
private static String TAG = "WallpaperManager";
@@ -134,7 +135,7 @@
* screen coordinates.
*/
public static final String COMMAND_TAP = "android.wallpaper.tap";
-
+
/**
* Command for {@link #sendWallpaperCommand}: reported by the wallpaper
* host when the user releases a secondary pointer on an empty area
@@ -177,7 +178,7 @@
public static final int FLAG_SET_LOCK = 1 << 1;
private final Context mContext;
-
+
/**
* Special drawable that draws a wallpaper as fast as possible. Assumes
* no scaling or placement off (0,0) of the wallpaper (this should be done
@@ -258,19 +259,19 @@
return mHeight;
}
}
-
+
static class Globals extends IWallpaperManagerCallback.Stub {
private IWallpaperManager mService;
private Bitmap mWallpaper;
private Bitmap mDefaultWallpaper;
-
+
private static final int MSG_CLEAR_WALLPAPER = 1;
-
+
Globals(Looper looper) {
IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
mService = IWallpaperManager.Stub.asInterface(b);
}
-
+
public void onWallpaperChanged() {
/* The wallpaper has changed but we shouldn't eagerly load the
* wallpaper as that would be inefficient. Reset the cached wallpaper
@@ -366,7 +367,7 @@
return null;
}
}
-
+
private static final Object sSync = new Object[0];
private static Globals sGlobals;
@@ -377,7 +378,7 @@
}
}
}
-
+
/*package*/ WallpaperManager(Context context, Handler handler) {
mContext = context;
initGlobals(context.getMainLooper());
@@ -390,18 +391,18 @@
return (WallpaperManager)context.getSystemService(
Context.WALLPAPER_SERVICE);
}
-
+
/** @hide */
public IWallpaperManager getIWallpaperManager() {
return sGlobals.mService;
}
-
+
/**
* Retrieve the current system wallpaper; if
* no wallpaper is set, the system built-in static wallpaper is returned.
* This is returned as an
* abstract Drawable that you can install in a View to display whatever
- * wallpaper the user has currently set.
+ * wallpaper the user has currently set.
*
* @return Returns a Drawable object that will draw the wallpaper.
*/
@@ -588,7 +589,7 @@
* Retrieve the current system wallpaper; if there is no wallpaper set,
* a null pointer is returned. This is returned as an
* abstract Drawable that you can install in a View to display whatever
- * wallpaper the user has currently set.
+ * wallpaper the user has currently set.
*
* @return Returns a Drawable object that will draw the wallpaper or a
* null pointer if these is none.
@@ -641,7 +642,7 @@
/**
* Like {@link #getDrawable()} but returns a Bitmap.
- *
+ *
* @hide
*/
public Bitmap getBitmap() {
@@ -1248,7 +1249,7 @@
* are floating point numbers ranging from 0 to 1, representing where the
* wallpaper should be positioned within the screen space. These only
* make sense when the wallpaper is larger than the display.
- *
+ *
* @param windowToken The window who these offsets should be associated
* with, as returned by {@link android.view.View#getWindowToken()
* View.getWindowToken()}.
@@ -1271,17 +1272,17 @@
* specify the step size between virtual screens. For example, if the
* launcher has 3 virtual screens, it would specify an xStep of 0.5,
* since the X offset for those screens are 0.0, 0.5 and 1.0
- * @param xStep The X offset delta from one screen to the next one
+ * @param xStep The X offset delta from one screen to the next one
* @param yStep The Y offset delta from one screen to the next one
*/
public void setWallpaperOffsetSteps(float xStep, float yStep) {
mWallpaperXStep = xStep;
mWallpaperYStep = yStep;
}
-
+
/**
* Send an arbitrary command to the current active wallpaper.
- *
+ *
* @param windowToken The window who these offsets should be associated
* with, as returned by {@link android.view.View#getWindowToken()
* View.getWindowToken()}.
@@ -1306,7 +1307,8 @@
/**
* Returns whether wallpapers are supported for the calling user. If this function returns
- * false, any attempts to changing the wallpaper will have no effect.
+ * {@code false}, any attempts to changing the wallpaper will have no effect,
+ * and any attempt to obtain of the wallpaper will return {@code null}.
*/
public boolean isWallpaperSupported() {
if (sGlobals.mService == null) {
@@ -1322,11 +1324,31 @@
}
/**
+ * Returns whether the calling package is allowed to set the wallpaper for the calling user.
+ * If this function returns {@code false}, any attempts to change the wallpaper will have
+ * no effect. Always returns {@code true} for device owner and profile owner.
+ *
+ * @see android.os.UserManager#DISALLOW_SET_WALLPAPER
+ */
+ public boolean isWallpaperSettingAllowed() {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ } else {
+ try {
+ return sGlobals.mService.isWallpaperSettingAllowed(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+ return false;
+ }
+
+ /**
* Clear the offsets previously associated with this window through
* {@link #setWallpaperOffsets(IBinder, float, float)}. This reverts
* the window to its default state, where it does not cause the wallpaper
* to scroll from whatever its last offsets were.
- *
+ *
* @param windowToken The window who these offsets should be associated
* with, as returned by {@link android.view.View#getWindowToken()
* View.getWindowToken()}.
@@ -1339,7 +1361,7 @@
// Ignore.
}
}
-
+
/**
* Remove any currently set wallpaper, reverting to the system's built-in
* wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 5622207..9f1a9cf0 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -48,7 +48,6 @@
*/
private final long mEndTimeStamp;
-
/**
* Non-null array indicates the query enumerates over uids.
*/
@@ -165,7 +164,18 @@
*/
public static final int ROAMING_ROAMING = 0x2;
+ /**
+ * Special TAG value matching any tag.
+ */
+ public static final int TAG_ANY = android.net.NetworkStats.TAG_ALL;
+
+ /**
+ * Special TAG value for total data across all tags
+ */
+ public static final int TAG_ALL = android.net.NetworkStats.TAG_NONE;
+
private int mUid;
+ private int mTag;
private int mState;
private int mRoaming;
private long mBeginTimeStamp;
@@ -192,6 +202,14 @@
return uid;
}
+ private static int convertTag(int tag) {
+ switch (tag) {
+ case android.net.NetworkStats.TAG_ALL: return TAG_ANY;
+ case android.net.NetworkStats.TAG_NONE: return TAG_ALL;
+ }
+ return tag;
+ }
+
private static int convertRoaming(int roaming) {
switch (roaming) {
case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
@@ -218,6 +236,14 @@
}
/**
+ * Tag of the bucket.<p />
+ * @return Bucket tag.
+ */
+ public int getTag() {
+ return mTag;
+ }
+
+ /**
* Usage state. One of the following values:<p/>
* <ul>
* <li>{@link #STATE_ALL}</li>
@@ -363,9 +389,9 @@
* Collects summary results and sets summary enumeration mode.
* @throws RemoteException
*/
- void startSummaryEnumeration() throws RemoteException {
- mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp, false);
-
+ void startSummaryEnumeration(boolean includeTags) throws RemoteException {
+ mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
+ includeTags);
mEnumerationIndex = 0;
}
@@ -373,10 +399,17 @@
* Collects history results for uid and resets history enumeration index.
*/
void startHistoryEnumeration(int uid) {
+ startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE);
+ }
+
+ /**
+ * Collects history results for uid and resets history enumeration index.
+ */
+ void startHistoryEnumeration(int uid, int tag) {
mHistory = null;
try {
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
- android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
+ android.net.NetworkStats.SET_ALL, tag,
NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
setSingleUid(uid);
} catch (RemoteException e) {
@@ -434,6 +467,7 @@
private void fillBucketFromSummaryEntry(Bucket bucketOut) {
bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
+ bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
bucketOut.mBeginTimeStamp = mStartTimeStamp;
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 1a9bf4e..4dc636b 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -82,10 +82,11 @@
}
/**
* Query network usage statistics summaries. Result is summarised data usage for the whole
- * device. Result is a single Bucket aggregated over time, state and uid. This means the
- * bucket's start and end timestamp are going to be the same as the 'startTime' and 'endTime'
- * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
- * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * device. Result is a single Bucket aggregated over time, state, uid, tag and roaming. This
+ * means the bucket's start and end timestamp are going to be the same as the 'startTime' and
+ * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
+ * {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_ALL}
+ * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -114,11 +115,22 @@
}
/**
+ * Query network usage statistics summaries aggregated across tags.
+ *
+ * #see querySummaryForUser(int, String, long, long, boolean)
+ */
+ public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
+ long endTime) throws SecurityException, RemoteException {
+ return querySummaryForUser(networkType, subscriberId, startTime, endTime,
+ false /* includeTags */);
+ }
+
+ /**
* Query network usage statistics summaries. Result is summarised data usage for all uids
* belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
* This means the bucket's start and end timestamp are going to be the same as the 'startTime'
- * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid
- * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid
+ * {@link NetworkStats.Bucket#UID_ALL}.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -128,11 +140,13 @@
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
+ * @param includeTags whether to include network tags. If {@code true}, tags will be returned
+ * and history retention may be shorter.
* @return Bucket object or null if permissions are insufficient or error happened during
* statistics collection.
*/
public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
+ long endTime, boolean includeTags) throws SecurityException, RemoteException {
NetworkTemplate template = createTemplate(networkType, subscriberId);
if (template == null) {
return null;
@@ -140,18 +154,28 @@
NetworkStats stats;
stats = new NetworkStats(mContext, template, startTime, endTime);
- stats.startSummaryEnumeration();
+ stats.startSummaryEnumeration(includeTags);
stats.close();
return stats.getSummaryAggregate();
}
/**
+ * Query network usage statistics summaries aggregated across tags.
+ *
+ * #see querySummary(int, String, long, long, boolean)
+ */
+ public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
+ long endTime) throws SecurityException, RemoteException {
+ return querySummary(networkType, subscriberId, startTime, endTime, false /* includeTags */);
+ }
+
+ /**
* Query network usage statistics summaries. Result filtered to include only uids belonging to
* calling user. Result is aggregated over time, hence all buckets will have the same start and
- * end timestamps. Not aggregated over state, uid, or roaming. This means buckets' start and end
- * timestamps are going to be the same as the 'startTime' and 'endTime' parameters, state and
- * uid are going to vary.
+ * end timestamps. Not aggregated over state or uid or tag. This means buckets' start and end
+ * timestamps are going to be the same as the 'startTime' and 'endTime' parameters. State,
+ * uid and tag are going to vary.
*
* @param networkType As defined in {@link ConnectivityManager}, e.g.
* {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
@@ -161,11 +185,13 @@
* {@link java.lang.System#currentTimeMillis}.
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
+ * @param includeTags whether to include network tags. If {@code true}, tags will be returned
+ * and history retention may be shorter.
* @return Statistics object or null if permissions are insufficient or error happened during
* statistics collection.
*/
public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
- long endTime) throws SecurityException, RemoteException {
+ long endTime, boolean includeTags) throws SecurityException, RemoteException {
NetworkTemplate template = createTemplate(networkType, subscriberId);
if (template == null) {
return null;
@@ -173,17 +199,28 @@
NetworkStats result;
result = new NetworkStats(mContext, template, startTime, endTime);
- result.startSummaryEnumeration();
+ result.startSummaryEnumeration(includeTags);
return result;
}
/**
- * Query network usage statistics details. Only usable for uids belonging to calling user.
- * Result is aggregated over state but not aggregated over time. This means buckets' start and
- * end timestamps are going to be between 'startTime' and 'endTime' parameters, state is going
- * to be {@link NetworkStats.Bucket#STATE_ALL} and uid the same as the 'uid' parameter. roaming
- * is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * Query network usage statistics details for a given uid.
+ *
+ * #see queryDetailsForUidTag(int, String, long, long, int, int)
+ */
+ public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
+ long startTime, long endTime, int uid) throws SecurityException, RemoteException {
+ return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid,
+ NetworkStats.Bucket.TAG_ALL);
+ }
+
+ /**
+ * Query network usage statistics details for a given uid and tag. Only usable for uids
+ * belonging to calling user. Result is aggregated over state but not aggregated over time.
+ * This means buckets' start and end timestamps are going to be between 'startTime' and
+ * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the
+ * same as the 'uid' parameter and tag the same as 'tag' parameter.
* <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets. Since bucket length is in the order of hours, this
* method cannot be used to measure data usage on a fine grained time scale.
@@ -197,11 +234,14 @@
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
+ * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_ANY} for any tags, use
+ * {@link NetworkStats.Bucket#TAG_ALL} to aggregate over tags.
* @return Statistics object or null if permissions are insufficient or error happened during
* statistics collection.
*/
- public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
- long startTime, long endTime, int uid) throws SecurityException, RemoteException {
+ public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
+ long startTime, long endTime, int uid, int tag) throws SecurityException,
+ RemoteException {
NetworkTemplate template = createTemplate(networkType, subscriberId);
if (template == null) {
return null;
@@ -209,7 +249,7 @@
NetworkStats result;
result = new NetworkStats(mContext, template, startTime, endTime);
- result.startHistoryEnumeration(uid);
+ result.startHistoryEnumeration(uid, tag);
return result;
}
@@ -218,8 +258,9 @@
* Query network usage statistics details. Result filtered to include only uids belonging to
* calling user. Result is aggregated over state but not aggregated over time or uid. This means
* buckets' start and end timestamps are going to be between 'startTime' and 'endTime'
- * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid will vary.
- * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
+ * tag {@link NetworkStats.Bucket#TAG_ALL} and roaming is going to be
+ * {@link NetworkStats.Bucket#ROAMING_ALL}.
* <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets. Since bucket length is in the order of hours, this
* method cannot be used to measure data usage on a fine grained time scale.
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 3219fe7..55b8f03 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -38,6 +38,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Adapter;
import android.widget.AdapterView;
@@ -234,6 +235,25 @@
}
}
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ try {
+ super.onLayout(changed, left, top, right, bottom);
+ } catch (final RuntimeException e) {
+ Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
+ removeViewInLayout(mView);
+ View child = getErrorView();
+ prepareView(child);
+ addViewInLayout(child, 0, child.getLayoutParams());
+ measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+ child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
+ child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
+ mView = child;
+ mViewMode = VIEW_MODE_ERROR;
+ }
+ }
+
/**
* Provide guidance about the size of this widget to the AppWidgetManager. The widths and
* heights should correspond to the full area the AppWidgetHostView is given. Padding added by
@@ -381,7 +401,7 @@
remoteViews.reapply(mContext, mView, mOnClickHandler);
content = mView;
recycled = true;
- if (LOGD) Log.d(TAG, "was able to recycled existing layout");
+ if (LOGD) Log.d(TAG, "was able to recycle existing layout");
} catch (RuntimeException e) {
exception = e;
}
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 8919d51..3d8b091 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -49,6 +49,7 @@
/** {@link #uid} value when UID details unavailable. */
public static final int UID_ALL = -1;
/** {@link #tag} value matching any tag. */
+ // TODO: Rename TAG_ALL to TAG_ANY.
public static final int TAG_ALL = -1;
/** {@link #set} value for all sets combined, not including debug sets. */
public static final int SET_ALL = -1;
@@ -64,6 +65,7 @@
public static final int SET_DBG_VPN_OUT = 1002;
/** {@link #tag} value for total data across all tags. */
+ // TODO: Rename TAG_NONE to TAG_ALL.
public static final int TAG_NONE = 0;
/** {@link #set} value for all roaming values. */
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index c776ef8..e841dfe 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -479,6 +479,11 @@
public static String DIRECTORY_DOCUMENTS = "Documents";
/**
+ * Standard directory in which user managed files are stored.
+ */
+ public static String DIRECTORY_HOME = "Home";
+
+ /**
* List of standard storage directories.
* <p>
* Each of its values have its own constant:
@@ -493,6 +498,7 @@
* <li>{@link #DIRECTORY_DOWNLOADS}
* <li>{@link #DIRECTORY_DCIM}
* <li>{@link #DIRECTORY_DOCUMENTS}
+ * <li>{@link #DIRECTORY_HOME}
* </ul>
* @hide
*/
@@ -506,7 +512,8 @@
DIRECTORY_MOVIES,
DIRECTORY_DOWNLOADS,
DIRECTORY_DCIM,
- DIRECTORY_DOCUMENTS
+ DIRECTORY_DOCUMENTS,
+ DIRECTORY_HOME
};
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1ac798b..ad7b4e2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -463,9 +463,11 @@
public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
/**
- * Hidden user restriction to disallow access to wallpaper manager APIs. This user restriction
- * is always set for managed profiles.
+ * Hidden user restriction to disallow access to wallpaper manager APIs. This restriction
+ * generally means that wallpapers are not supported for the particular user. This user
+ * restriction is always set for managed profiles, because such profiles don't have wallpapers.
* @hide
+ * @see #DISALLOW_SET_WALLPAPER
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
@@ -473,6 +475,19 @@
public static final String DISALLOW_WALLPAPER = "no_wallpaper";
/**
+ * User restriction to disallow setting a wallpaper. Profile owner and device owner
+ * are able to set wallpaper regardless of this restriction.
+ * The default value is <code>false</code>.
+ *
+ * <p>Key for user restrictions.
+ * <p>Type: Boolean
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
+
+ /**
* Specifies if the user is not allowed to reboot the device into safe boot mode.
* This can only be set by device owners and profile owners on the primary user.
* The default value is <code>false</code>.
@@ -535,9 +550,7 @@
* affected. The default value is <code>false</code>.
*
* <p>Key for user restrictions.
- *
* <p>Type: Boolean
- *
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
* @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
* @see #getUserRestrictions()
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 2c7bf65..11737c6 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.annotation.SystemApi;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
@@ -24,7 +25,8 @@
import java.util.Objects;
/**
- * Condition information from condition providers.
+ * Condition information from condition providers. Used to tell the system to enter Do Not Disturb
+ * mode and request that the system exit Do Not Disturb mode.
*/
public class Condition implements Parcelable {
@@ -38,14 +40,47 @@
public static final int FLAG_RELEVANT_NOW = 1 << 0;
public static final int FLAG_RELEVANT_ALWAYS = 1 << 1;
+ /**
+ * The URI representing the condition being updated.
+ * See {@link android.app.AutomaticZenRule#getConditionId()}.
+ */
public final Uri id;
- public final String summary;
- public final String line1;
- public final String line2;
- public final int icon;
- public final int state;
- public final int flags;
+ /**
+ * A summary of what the rule encoded in {@link #id} means when it is enabled. User visible
+ * if the state of the condition is {@link #STATE_TRUE}.
+ */
+ public final String summary;
+
+ /**
+ * Additional information about what the rule encoded in {@link #id} means when it is enabled.
+ * User visible if the state of the condition is {@link #STATE_TRUE}.
+ */
+ public final String line1;
+
+ /**
+ * Additional information about what the rule encoded in {@link #id} means when it is enabled.
+ * User visible if the state of the condition is {@link #STATE_TRUE}.
+ */
+ public final String line2;
+
+ /**
+ * The state of this condition. {@link #STATE_TRUE} will enable Do Not Disturb mode. Any other
+ * state will turn Do Not Disturb off for this rule. Note that Do Not Disturb might still be
+ * enabled globally if other conditions are in a {@link #STATE_TRUE} state.
+ */
+ public final int state;
+
+ @SystemApi
+ public final int flags;
+ @SystemApi
+ public final int icon;
+
+ public Condition(Uri id, String summary, String line1, String line2, int state) {
+ this(id, summary, line1, line2, -1, state, FLAG_RELEVANT_ALWAYS);
+ }
+
+ @SystemApi
public Condition(Uri id, String summary, String line1, String line2, int icon,
int state, int flags) {
if (id == null) throw new IllegalArgumentException("id is required");
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index eff09d6..adcc9d6 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,6 +17,7 @@
package android.service.notification;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.app.INotificationManager;
import android.app.Service;
import android.content.ComponentName;
@@ -102,13 +103,10 @@
abstract public void onConnected();
/**
- * Called when the system wants to know the state of Conditions managed by this provider.
- *
- * Implementations should evaluate the state of all subscribed conditions, and provide updates
- * by calling {@link #notifyCondition(Condition)} or {@link #notifyConditions(Condition...)}.
- * @param relevance
+ * @removed
*/
- abstract public void onRequestConditions(int relevance);
+ @SystemApi
+ public void onRequestConditions(int relevance) {}
/**
* Called by the system when there is a new {@link Condition} to be managed by this provider.
@@ -131,7 +129,11 @@
}
/**
- * Informs the notification manager that the state of a Condition has changed.
+ * Informs the notification manager that the state of a Condition has changed. Use this method
+ * to put the system into Do Not Disturb mode or request that it exits Do Not Disturb mode. This
+ * call will be ignored unless there is an enabled {@link android.app.AutomaticZenRule} owned by
+ * service that has an {@link android.app.AutomaticZenRule#getConditionId()} equal to this
+ * {@link Condition#id}.
* @param condition the condition that has changed.
*/
public final void notifyCondition(Condition condition) {
@@ -140,7 +142,8 @@
}
/**
- * Informs the notification manager that the state of one or more Conditions has changed.
+ * Informs the notification manager that the state of one or more Conditions has changed. See
+ * {@link #notifyCondition(Condition)} for restrictions.
* @param conditions the changed conditions.
*/
public final void notifyConditions(Condition... conditions) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 27ea92d..1740f07 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -381,4 +381,9 @@
* @param receiver The receiver to deliver the results to.
*/
void requestAppKeyboardShortcuts(IResultReceiver receiver);
+
+ /**
+ * Retrieves the current stable insets from the primary display.
+ */
+ void getStableInsets(out Rect outInsets);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 78a63a6..8b06ecf 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -252,6 +252,17 @@
}
/**
+ * Sets the library directory to use as a search path for vulkan layers.
+ *
+ * @param libDir A directory that contains vulkan layers
+ *
+ * @hide
+ */
+ public static void setLibDir(String libDir) {
+ ThreadedRenderer.setupVulkanLayerPath(libDir);
+ }
+
+ /**
* Creates a hardware renderer using OpenGL.
*
* @param translucent True if the surface is translucent, false otherwise
@@ -979,6 +990,7 @@
}
static native void setupShadersDiskCache(String cacheFile);
+ static native void setupVulkanLayerPath(String layerPath);
private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
private static native void nSetProcessStatsBuffer(long nativeProxy, int fd);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 96b63d1..c68a740 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -34,7 +34,6 @@
import android.media.session.MediaController;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -273,7 +272,7 @@
private Callback mCallback;
private OnWindowDismissedCallback mOnWindowDismissedCallback;
private WindowControllerCallback mWindowControllerCallback;
- private RestrictedCaptionAreaListener mRestrictedCaptionAreaListener;
+ private OnRestrictedCaptionAreaChangedListener mOnRestrictedCaptionAreaChangedListener;
private Rect mRestrictedCaptionAreaRect;
private WindowManager mWindowManager;
private IBinder mAppToken;
@@ -596,7 +595,7 @@
/**
* Callback for clients that want to be aware of where caption draws content.
*/
- public interface RestrictedCaptionAreaListener {
+ public interface OnRestrictedCaptionAreaChangedListener {
/**
* Called when the area where caption draws content changes.
*
@@ -856,8 +855,8 @@
*
* @param listener Callback that will be called when the area changes.
*/
- public final void setRestrictedCaptionAreaListener(RestrictedCaptionAreaListener listener) {
- mRestrictedCaptionAreaListener = listener;
+ public final void setRestrictedCaptionAreaListener(OnRestrictedCaptionAreaChangedListener listener) {
+ mOnRestrictedCaptionAreaChangedListener = listener;
mRestrictedCaptionAreaRect = listener != null ? new Rect() : null;
}
@@ -2126,17 +2125,20 @@
/** @hide */
public void notifyRestrictedCaptionAreaCallback(int left, int top, int right, int bottom) {
- if (mRestrictedCaptionAreaListener != null) {
+ if (mOnRestrictedCaptionAreaChangedListener != null) {
mRestrictedCaptionAreaRect.set(left, top, right, bottom);
- mRestrictedCaptionAreaListener.onRestrictedCaptionAreaChanged(
+ mOnRestrictedCaptionAreaChangedListener.onRestrictedCaptionAreaChanged(
mRestrictedCaptionAreaRect);
}
}
/**
* Set what color should the caption controls be. By default the system will try to determine
- * the color from the theme. You can overwrite this by using {@link #DECOR_CAPTION_SHADE_DARK}
- * or {@link #DECOR_CAPTION_SHADE_DARK}.
+ * the color from the theme. You can overwrite this by using {@link #DECOR_CAPTION_SHADE_DARK},
+ * {@link #DECOR_CAPTION_SHADE_LIGHT}, or {@link #DECOR_CAPTION_SHADE_AUTO}.
+ * @see #DECOR_CAPTION_SHADE_DARK
+ * @see #DECOR_CAPTION_SHADE_LIGHT
+ * @see #DECOR_CAPTION_SHADE_AUTO
*/
public abstract void setDecorCaptionShade(int decorCaptionShade);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index a11897d..5b4a368 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3930,7 +3930,7 @@
super.onInitializeAccessibilityNodeInfoForItem(view, position, info);
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
- final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
+ final boolean isHeading = lp != null && lp.viewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
final boolean isSelected = isItemChecked(position);
final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
position, 1, 0, 1, isHeading, isSelected);
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index c4ec714..478a56d 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -16,6 +16,7 @@
package com.android.internal.app;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -165,6 +166,14 @@
localized.setVisibility(View.VISIBLE);
text.setTextLocale(Locale.getDefault());
}
+ if (mCountryMode) {
+ int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
+ //noinspection ResourceType
+ convertView.setLayoutDirection(layoutDir);
+ text.setTextDirection(layoutDir == View.LAYOUT_DIRECTION_RTL
+ ? View.TEXT_DIRECTION_RTL
+ : View.TEXT_DIRECTION_LTR);
+ }
}
return convertView;
}
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a38139f..597c522 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -58,6 +58,7 @@
private final Rect mInsets = new Rect();
private final int mSnapMode;
private final float mFixedRatio;
+ private boolean mIsHorizontalDivision;
/** The first target which is still splitting the screen */
private final SnapTarget mFirstSplitTarget;
@@ -78,6 +79,7 @@
mDividerSize = dividerSize;
mDisplayWidth = displayWidth;
mDisplayHeight = displayHeight;
+ mIsHorizontalDivision = isHorizontalDivision;
mInsets.set(insets);
mSnapMode = res.getInteger(
com.android.internal.R.integer.config_dockedStackDividerSnapMode);
@@ -130,10 +132,12 @@
public float calculateDismissingFraction(int position) {
if (position < mFirstSplitTarget.position) {
- return 1f - (float) position / mFirstSplitTarget.position;
+ return 1f - (float) (position - getStartInset())
+ / (mFirstSplitTarget.position - getStartInset());
} else if (position > mLastSplitTarget.position) {
return (float) (position - mLastSplitTarget.position)
- / (mDismissEndTarget.position - mLastSplitTarget.position);
+ / (mDismissEndTarget.position - getEndInset()
+ - mLastSplitTarget.position - mDividerSize);
}
return 0f;
}
@@ -167,6 +171,22 @@
return mDismissEndTarget;
}
+ private int getStartInset() {
+ if (mIsHorizontalDivision) {
+ return mInsets.top;
+ } else {
+ return mInsets.left;
+ }
+ }
+
+ private int getEndInset() {
+ if (mIsHorizontalDivision) {
+ return mInsets.bottom;
+ } else {
+ return mInsets.right;
+ }
+ }
+
private SnapTarget snap(int position, boolean hardDismiss) {
int minIndex = -1;
float minDistance = Float.MAX_VALUE;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8c4683d..ffa3fa6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -184,6 +184,7 @@
$(LOCAL_PATH)/android/graphics \
$(LOCAL_PATH)/../../libs/hwui \
$(LOCAL_PATH)/../../../native/opengl/libs \
+ $(LOCAL_PATH)/../../../native/vulkan/include \
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
@@ -233,6 +234,7 @@
libEGL \
libGLESv1_CM \
libGLESv2 \
+ libvulkan \
libETC1 \
libhardware \
libhardware_legacy \
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index edced56..8c907dd 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -27,6 +27,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/egl_cache.h>
+#include <vulkan/vulkan_loader_data.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>
@@ -618,6 +619,18 @@
}
// ----------------------------------------------------------------------------
+// Layers
+// ----------------------------------------------------------------------------
+
+static void android_view_ThreadedRenderer_setupVulkanLayerPath(JNIEnv* env, jobject clazz,
+ jstring layerPath) {
+
+ const char* layerArray = env->GetStringUTFChars(layerPath, NULL);
+ vulkan::LoaderData::GetInstance().layer_path = layerArray;
+ env->ReleaseStringUTFChars(layerPath, layerArray);
+}
+
+// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -658,6 +671,8 @@
{ "nDumpProfileData", "([BLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileData },
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
(void*) android_view_ThreadedRenderer_setupShadersDiskCache },
+ { "setupVulkanLayerPath", "(Ljava/lang/String;)V",
+ (void*) android_view_ThreadedRenderer_setupVulkanLayerPath },
{ "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index f036b19..40dbe27 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -322,6 +322,19 @@
}
/**
+ * Insets the rectangle on all sides specified by the dimensions of the {@code insets}
+ * rectangle.
+ * @hide
+ * @param insets The rectangle specifying the insets on all side.
+ */
+ public void inset(Rect insets) {
+ left += insets.left;
+ top += insets.top;
+ right -= insets.right;
+ bottom -= insets.bottom;
+ }
+
+ /**
* Returns true if (x,y) is inside the rectangle. The left and top are
* considered to be inside, while the right and bottom are not. This means
* that for a x,y to be contained: left <= x < right and top <= y < bottom.
diff --git a/include/androidfw/LocaleData.h b/include/androidfw/LocaleData.h
index add0ab5..b14829d 100644
--- a/include/androidfw/LocaleData.h
+++ b/include/androidfw/LocaleData.h
@@ -29,6 +29,8 @@
void localeDataComputeScript(char out[4], const char* language, const char* region);
+bool localeDataIsCloseToUsEnglish(const char* region);
+
} // namespace android
#endif // _LIBS_UTILS_LOCALE_DATA_H
diff --git a/libs/androidfw/LocaleData.cpp b/libs/androidfw/LocaleData.cpp
index c0c3ab8..038ef58 100644
--- a/libs/androidfw/LocaleData.cpp
+++ b/libs/androidfw/LocaleData.cpp
@@ -70,13 +70,17 @@
//
// Returns the number of ancestors written in the output, which is always
// at least one.
+//
+// (If 'out' is nullptr, we do everything the same way but we simply don't write
+// any results in 'out'.)
size_t findAncestors(uint32_t* out, ssize_t* stop_list_index,
uint32_t packed_locale, const char* script,
const uint32_t* stop_list, size_t stop_set_length) {
uint32_t ancestor = packed_locale;
size_t count = 0;
do {
- out[count++] = ancestor;
+ if (out != nullptr) out[count] = ancestor;
+ count++;
for (size_t i = 0; i < stop_set_length; i++) {
if (stop_list[i] == ancestor) {
*stop_list_index = (ssize_t) i;
@@ -93,10 +97,9 @@
const char* script,
const uint32_t* request_ancestors,
size_t request_ancestors_count) {
- uint32_t supported_ancestors[MAX_PARENT_DEPTH+1];
ssize_t request_ancestors_index;
const size_t supported_ancestor_count = findAncestors(
- supported_ancestors, &request_ancestors_index,
+ nullptr, &request_ancestors_index,
supported, script,
request_ancestors, request_ancestors_count);
// Since both locales share the same root, there will always be a shared
@@ -198,4 +201,19 @@
}
}
+const uint32_t ENGLISH_STOP_LIST[2] = {
+ 0x656E0000lu, // en
+ 0x656E8400lu, // en-001
+};
+const char ENGLISH_CHARS[2] = {'e', 'n'};
+const char LATIN_CHARS[4] = {'L', 'a', 't', 'n'};
+
+bool localeDataIsCloseToUsEnglish(const char* region) {
+ const uint32_t locale = packLocale(ENGLISH_CHARS, region);
+ ssize_t stop_list_index;
+ findAncestors(nullptr, &stop_list_index, locale, LATIN_CHARS, ENGLISH_STOP_LIST, 2);
+ // A locale is like US English if we see "en" before "en-001" in its ancestor list.
+ return stop_list_index == 0; // 'en' is first in ENGLISH_STOP_LIST
+}
+
} // namespace android
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 71e9c92..1d9fe35 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2196,7 +2196,32 @@
// The languages of the two resources are not the same. We can only
// assume that one of the two resources matched the request because one
// doesn't have a language and the other has a matching language.
- return (language[0] != 0);
+ //
+ // We consider the one that has the language specified a better match.
+ //
+ // The exception is that we consider no-language resources a better match
+ // for US English and similar locales than locales that are a descendant
+ // of Internatinal English (en-001), since no-language resources are
+ // where the US English resource have traditionally lived for most apps.
+ if (requested->language[0] == 'e' && requested->language[1] == 'n') {
+ if (requested->country[0] == 'U' && requested->country[1] == 'S') {
+ // For US English itself, we consider a no-locale resource a
+ // better match if the other resource has a country other than
+ // US specified.
+ if (language[0] != '\0') {
+ return country[0] == '\0' || (country[0] == 'U' && country[1] == 'S');
+ } else {
+ return !(o.country[0] == '\0' || (o.country[0] == 'U' && o.country[1] == 'S'));
+ }
+ } else if (localeDataIsCloseToUsEnglish(requested->country)) {
+ if (language[0] != '\0') {
+ return localeDataIsCloseToUsEnglish(country);
+ } else {
+ return !localeDataIsCloseToUsEnglish(o.country);
+ }
+ }
+ }
+ return (language[0] != '\0');
}
// If we are here, both the resources have the same non-empty language as
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 1941563..7b38640 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -592,4 +592,52 @@
EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
}
+// Default resources are considered better matches for US English
+// and US-like English locales than International English locales
+TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) {
+ ResTable_config config1, config2, request;
+
+ fillIn("en", "US", NULL, NULL, &request);
+ fillIn(NULL, NULL, NULL, NULL, &config1);
+ fillIn("en", "001", NULL, NULL, &config2);
+ // default is better than International English
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("en", "US", NULL, NULL, &request);
+ fillIn(NULL, NULL, NULL, NULL, &config1);
+ fillIn("en", "GB", NULL, NULL, &config2);
+ // default is better than British English
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("en", "PR", NULL, NULL, &request);
+ fillIn(NULL, NULL, NULL, NULL, &config1);
+ fillIn("en", "001", NULL, NULL, &config2);
+ // Even for Puerto Rico, default is better than International English
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("en", "US", NULL, NULL, &request);
+ fillIn("en", NULL, NULL, NULL, &config1);
+ fillIn(NULL, NULL, NULL, NULL, &config2);
+ // "English" is better than default, since it's a parent of US English
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("en", "PR", NULL, NULL, &request);
+ fillIn("en", NULL, NULL, NULL, &config1);
+ fillIn(NULL, NULL, NULL, NULL, &config2);
+ // "English" is better than default, since it's a parent of Puerto Rico English
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("en", "US", NULL, NULL, &request);
+ fillIn(NULL, NULL, NULL, NULL, &config1);
+ fillIn("en", "PR", NULL, NULL, &config2);
+ // For US English itself, we prefer default to its siblings in the parent tree
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+}
+
} // namespace android
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index 71e87cb..eea91a0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -129,9 +129,11 @@
@Override
public void onChanged() {
- // TODO: This is causing b/22765812
- mSelection.clear();
mModelIds = mAdapter.getModelIds();
+
+ // Update the selection to remove any disappeared IDs.
+ mSelection.cancelProvisionalSelection();
+ mSelection.intersect(mModelIds);
}
@Override
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 1bfc19c..56e5a9b 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -27,6 +27,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.os.Environment;
import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
@@ -208,8 +209,10 @@
root.flags |= Root.FLAG_SUPPORTS_CREATE;
}
+ // Create the "Home" directory on disk, but don't the localized root.title
+ // since the directories shouldn't be localized.
root.visiblePath = new File(
- primaryVolume.getPathForUser(userId), root.rootId);
+ primaryVolume.getPathForUser(userId), Environment.DIRECTORY_HOME);
root.path = new File(
primaryVolume.getInternalPathForUser(userId), root.rootId);
try {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 743df99..892be2d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -167,6 +167,8 @@
public static final PageRange[] ALL_PAGES_ARRAY = new PageRange[]{PageRange.ALL_PAGES};
+ private boolean mIsOptionsUiBound = false;
+
private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
new PrinterAvailabilityDetector();
@@ -337,7 +339,7 @@
@Override
public void onStart() {
super.onStart();
- if (mState != STATE_INITIALIZING && mCurrentPrinter != null) {
+ if (mPrinterRegistry != null && mCurrentPrinter != null) {
mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
}
MetricsLogger.count(this, "print_preview", 1);
@@ -384,7 +386,10 @@
@Override
protected void onStop() {
mPrinterAvailabilityDetector.cancel();
- mPrinterRegistry.setTrackedPrinter(null);
+
+ if (mPrinterRegistry != null) {
+ mPrinterRegistry.setTrackedPrinter(null);
+ }
super.onStop();
}
@@ -1214,6 +1219,9 @@
mPrintButton = (ImageView) findViewById(R.id.print_button);
mPrintButton.setOnClickListener(clickListener);
+ // The UI is now initialized
+ mIsOptionsUiBound = true;
+
// Special prompt instead of destination spinner for the first time the user printed
if (!hasUserEverPrinted()) {
mShowDestinationPrompt = true;
@@ -1390,6 +1398,10 @@
}
void updateOptionsUi() {
+ if (!mIsOptionsUiBound) {
+ return;
+ }
+
// Always update the summary.
updateSummary();
@@ -1725,6 +1737,10 @@
}
private void updateSummary() {
+ if (!mIsOptionsUiBound) {
+ return;
+ }
+
CharSequence copiesText = null;
CharSequence mediaSizeText = null;
@@ -1912,9 +1928,12 @@
}
private void doFinish() {
+ if (mPrinterRegistry != null) {
+ mPrinterRegistry.setTrackedPrinter(null);
+ }
+
if (mState != STATE_INITIALIZING) {
mProgressMessageController.cancel();
- mPrinterRegistry.setTrackedPrinter(null);
mSpoolerProvider.destroy();
mPrintedDocument.finish();
mPrintedDocument.destroy();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 7ee53a2..c075703 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -835,7 +835,7 @@
public int getConnectionSummary() {
boolean profileConnected = false; // at least one profile is connected
boolean a2dpNotConnected = false; // A2DP is preferred but not connected
- boolean headsetNotConnected = false; // Headset is preferred but not connected
+ boolean hfpNotConnected = false; // HFP is preferred but not connected
for (LocalBluetoothProfile profile : getProfiles()) {
int connectionStatus = getProfileConnectionState(profile);
@@ -851,11 +851,12 @@
case BluetoothProfile.STATE_DISCONNECTED:
if (profile.isProfileReady()) {
- if ((profile instanceof A2dpProfile)||
+ if ((profile instanceof A2dpProfile) ||
(profile instanceof A2dpSinkProfile)){
a2dpNotConnected = true;
- } else if (profile instanceof HeadsetProfile) {
- headsetNotConnected = true;
+ } else if ((profile instanceof HeadsetProfile) ||
+ (profile instanceof HfpClientProfile)) {
+ hfpNotConnected = true;
}
}
break;
@@ -863,11 +864,11 @@
}
if (profileConnected) {
- if (a2dpNotConnected && headsetNotConnected) {
+ if (a2dpNotConnected && hfpNotConnected) {
return R.string.bluetooth_connected_no_headset_no_a2dp;
} else if (a2dpNotConnected) {
return R.string.bluetooth_connected_no_a2dp;
- } else if (headsetNotConnected) {
+ } else if (hfpNotConnected) {
return R.string.bluetooth_connected_no_headset;
} else {
return R.string.bluetooth_connected;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
new file mode 100755
index 0000000..9b699bc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handles the Handsfree HF role.
+ */
+final class HfpClientProfile implements LocalBluetoothProfile {
+ private static final String TAG = "HfpClientProfile";
+ private static boolean V = false;
+
+ private BluetoothHeadsetClient mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+
+ static final ParcelUuid[] SRC_UUIDS = {
+ BluetoothUuid.HSP_AG,
+ BluetoothUuid.Handsfree_AG,
+ };
+
+ static final String NAME = "HEADSET_CLIENT";
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 0;
+
+ // These callbacks run on the main thread.
+ private final class HfpClientServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothHeadsetClient) proxy;
+ // We just bound to the service, so refresh the UI for any connected HFP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "HfpClient profile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(
+ HfpClientProfile.this, BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+ mIsProfileReady=true;
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mIsProfileReady=false;
+ }
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ HfpClientProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new HfpClientServiceListener(),
+ BluetoothProfile.HEADSET_CLIENT);
+ }
+
+ @Override
+ public boolean isConnectable() {
+ return true;
+ }
+
+ @Override
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> srcs = getConnectedDevices();
+ if (srcs != null) {
+ for (BluetoothDevice src : srcs) {
+ if (src.equals(device)) {
+ // Connect to same device, Ignore it
+ Log.d(TAG,"Ignoring Connect");
+ return true;
+ }
+ }
+ // Handsfree HF only supports one source connection and hence it is OK to disconnect
+ // the only connected device here.
+ for (BluetoothDevice src : srcs) {
+ mService.disconnect(src);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ // Downgrade priority as user is disconnecting the headset.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+
+ @Override
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
+ }
+
+ @Override
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ @Override
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ @Override
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return NAME;
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ @Override
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_headset;
+ }
+
+ @Override
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_headset_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_headset_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ @Override
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_headset_hfp;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
+ BluetoothProfile.HEADSET_CLIENT, mService);
+ mService = null;
+ } catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up HfpClient proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index b05e34c..6226b23 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -20,6 +20,7 @@
import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
@@ -76,6 +77,7 @@
private A2dpProfile mA2dpProfile;
private A2dpSinkProfile mA2dpSinkProfile;
private HeadsetProfile mHeadsetProfile;
+ private HfpClientProfile mHfpClientProfile;
private MapProfile mMapProfile;
private final HidProfile mHidProfile;
private OppProfile mOppProfile;
@@ -150,6 +152,7 @@
Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
}
+ // A2DP SINK
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
if (mA2dpSinkProfile == null) {
if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
@@ -175,6 +178,22 @@
Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
}
+ // Headset HF
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
+ if (mHfpClientProfile == null) {
+ if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
+ mHfpClientProfile =
+ new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mHfpClientProfile, HfpClientProfile.NAME,
+ BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
+ }
+ } else if (mHfpClientProfile != null) {
+ Log.w(TAG,
+ "Warning: Hfp Client profile was previously added but the UUID is now missing.");
+ } else {
+ Log.d(TAG, "Handsfree Uuid not found.");
+ }
+
// OPP
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
if (mOppProfile == null) {
@@ -312,17 +331,26 @@
return mA2dpProfile;
}
- A2dpSinkProfile getA2dpSinkProfile() {
- if ((mA2dpSinkProfile != null)&&(mA2dpSinkProfile.isProfileReady()))
- return mA2dpSinkProfile;
- else
+ public A2dpSinkProfile getA2dpSinkProfile() {
+ if ((mA2dpSinkProfile != null) && (mA2dpSinkProfile.isProfileReady())) {
+ return mA2dpSinkProfile;
+ } else {
return null;
+ }
}
public HeadsetProfile getHeadsetProfile() {
return mHeadsetProfile;
}
+ public HfpClientProfile getHfpClientProfile() {
+ if ((mHfpClientProfile != null) && (mHfpClientProfile.isProfileReady())) {
+ return mHfpClientProfile;
+ } else {
+ return null;
+ }
+ }
+
public PbapServerProfile getPbapProfile(){
return mPbapProfile;
}
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_car.xml b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
index 072f614..5d754ef 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_car.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_car.xml
@@ -20,5 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Dirija com segurança"</string>
- <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições de direção e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
+ <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições da estrada e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings_car.xml b/packages/SystemUI/res/values-pt/strings_car.xml
index 072f614..5d754ef 100644
--- a/packages/SystemUI/res/values-pt/strings_car.xml
+++ b/packages/SystemUI/res/values-pt/strings_car.xml
@@ -20,5 +20,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="car_lockscreen_disclaimer_title" msgid="7997539137376896441">"Dirija com segurança"</string>
- <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições de direção e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
+ <string name="car_lockscreen_disclaimer_text" msgid="3061224684092952864">"Mantenha-se atento às condições da estrada e sempre obedeça às leis aplicáveis. As instruções podem ser imprecisas, incompletas, perigosas, inadequadas, proibidas ou envolver o cruzamento de áreas administrativas. As informações comerciais também podem ser imprecisas ou incompletas. Os dados não são exibidos em tempo real, e a precisão da localização não pode ser garantida. Enquanto dirige, não manuseie seu dispositivo móvel nem use apps que não tenham sido criados para o Android Auto."</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 32da3c6..c6c448d0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -897,10 +897,10 @@
<!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
<string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
- <!-- Title of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
+ <!-- Title of the confirmation dialog for deleting a user [CHAR LIMIT=NONE] -->
<string name="user_remove_user_title">Remove user?</string>
- <!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
+ <!-- Message of the confirmation dialog for deleting a user [CHAR LIMIT=NONE] -->
<string name="user_remove_user_message">All apps and data of this user will be deleted.</string>
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 0115f91..9e43bb4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -103,12 +103,9 @@
/**
* Updates the configuration based on the current state of the system
*/
- void update(Rect windowRect) {
- // Recompute some values based on the given state, since we can not rely on the resource
- // system to get certain values.
- boolean isLandscape = windowRect.width() > windowRect.height();
- hasTransposedNavBar = isLandscape && !isXLargeScreen;
- hasTransposedSearchBar = isLandscape && !isXLargeScreen;
+ void update(Rect systemInsets) {
+ hasTransposedNavBar = systemInsets.right > 0;
+ hasTransposedSearchBar = systemInsets.right > 0;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 5a60a19..1cceef4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -599,10 +599,14 @@
TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
SystemServicesProxy ssp = Recents.getSystemServices();
+ Rect systemInsets = new Rect();
+ ssp.getStableInsets(systemInsets);
Rect windowRect = ssp.getWindowRect();
+ calculateWindowStableInsets(systemInsets, windowRect);
+ windowRect.offsetTo(0, 0);
// Update the configuration for the current state
- config.update(windowRect);
+ config.update(systemInsets);
if (RecentsDebugFlags.Static.EnableSearchBar && tryAndBindSearchWidget) {
// Try and pre-emptively bind the search widget on startup to ensure that we
@@ -612,9 +616,6 @@
config.getSearchBarBounds(windowRect, mStatusBarHeight, mSearchBarBounds);
}
}
- Rect systemInsets = new Rect(0, mStatusBarHeight,
- (config.hasTransposedNavBar ? mNavBarWidth : 0),
- (config.hasTransposedNavBar ? 0 : mNavBarHeight));
config.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
mSearchBarBounds, mTaskStackBounds);
@@ -641,6 +642,26 @@
}
/**
+ * Given the stable insets and the rect for our window, calculates the insets that affect our
+ * window.
+ */
+ private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) {
+ Rect displayRect = Recents.getSystemServices().getDisplayRect();
+
+ // Display rect without insets - available app space
+ Rect appRect = new Rect(displayRect);
+ appRect.inset(inOutInsets);
+
+ // Our window intersected with available app space
+ Rect windowRectWithInsets = new Rect(windowRect);
+ windowRectWithInsets.intersect(appRect);
+ inOutInsets.left = windowRectWithInsets.left - windowRect.left;
+ inOutInsets.top = windowRectWithInsets.top - windowRect.top;
+ inOutInsets.right = windowRect.right - windowRectWithInsets.right;
+ inOutInsets.bottom = windowRect.bottom - windowRectWithInsets.bottom;
+ }
+
+ /**
* Preloads the icon of a task.
*/
private void preloadIcon(ActivityManager.RunningTaskInfo task) {
@@ -721,8 +742,9 @@
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
if (task.isFreeformTask()) {
- mTmpTransform = stackView.getStackAlgorithm().getStackTransform(task,
- stackView.getScroller().getStackScroll(), mTmpTransform, null);
+ mTmpTransform = stackView.getStackAlgorithm()
+ .getStackTransformScreenCoordinates(task,
+ stackView.getScroller().getStackScroll(), mTmpTransform, null);
Rect toTaskRect = new Rect();
mTmpTransform.rect.round(toTaskRect);
Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -783,7 +805,7 @@
// Get the transform for the running task
stackView.getScroller().setStackScrollToInitialState();
- mTmpTransform = stackView.getStackAlgorithm().getStackTransform(launchTask,
+ mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
return mTmpTransform;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index d22cd53..22ab794 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -47,6 +47,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -977,6 +978,16 @@
mWm.requestAppKeyboardShortcuts(receiver);
}
+ public void getStableInsets(Rect outStableInsets) {
+ if (mWm == null) return;
+
+ try {
+ WindowManagerGlobal.getWindowManagerService().getStableInsets(outStableInsets);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
public void focusPinnedStack() {
try {
mIam.setFocusedStack(PINNED_STACK_ID);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 3fdd771..6c1ff9b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -270,7 +270,8 @@
if (taskView == null) {
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
- layoutAlgorithm.getStackTransform(task, stackScroll, mTmpTransform, null);
+ layoutAlgorithm.getStackTransformScreenCoordinates(task, stackScroll, mTmpTransform,
+ null);
specs.add(composeAnimationSpec(taskView, mTmpTransform, true /* addHeaderBitmap */));
}
return specs;
@@ -290,7 +291,8 @@
// never happen)
specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));
} else {
- layoutAlgorithm.getStackTransform(t, stackScroll, mTmpTransform, null);
+ layoutAlgorithm.getStackTransformScreenCoordinates(t, stackScroll,
+ mTmpTransform, null);
specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7c695ce..46fdb2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -616,6 +616,18 @@
}
/**
+ * Like {@link #getStackTransform}, but in screen coordinates
+ */
+ public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
+ TaskViewTransform transformOut, TaskViewTransform frontTransform) {
+ Rect windowRect = Recents.getSystemServices().getWindowRect();
+ TaskViewTransform transform = getStackTransform(task, stackScroll, transformOut,
+ frontTransform);
+ transform.rect.offset(windowRect.left, windowRect.top);
+ return transform;
+ }
+
+ /**
* Update/get the transform.
*
* @param ignoreSingleTaskCase When set, will ensure that the transform computed does not take
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 0b20f7a..1e11fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -184,8 +184,17 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
- insets.getStableInsetRight(), insets.getStableInsetBottom());
+ if (mStableInsets.left != insets.getStableInsetLeft()
+ || mStableInsets.top != insets.getStableInsetTop()
+ || mStableInsets.right != insets.getStableInsetRight()
+ || mStableInsets.bottom != insets.getStableInsetBottom()) {
+ mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom());
+ if (mSnapAlgorithm != null) {
+ mSnapAlgorithm = null;
+ getSnapAlgorithm();
+ }
+ }
return super.onApplyWindowInsets(insets);
}
@@ -496,12 +505,42 @@
} else {
mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
}
+ SnapTarget closestDismissTarget = mSnapAlgorithm.getClosestDismissTarget(position);
+ float dimFraction = getDimFraction(position, closestDismissTarget);
+ mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
+ getStackIdForDismissTarget(closestDismissTarget),
+ dimFraction);
+ }
+
+ private float getDimFraction(int position, SnapTarget dismissTarget) {
float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
fraction = Math.max(0, Math.min(fraction, 1f));
fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
- mWindowManagerProxy.setResizeDimLayer(fraction != 0f,
- getStackIdForDismissTarget(mSnapAlgorithm.getClosestDismissTarget(position)),
- fraction);
+ if (hasInsetsAtDismissTarget(dismissTarget)) {
+
+ // Less darkening with system insets.
+ fraction *= 0.8f;
+ }
+ return fraction;
+ }
+
+ /**
+ * @return true if and only if there are system insets at the location of the dismiss target
+ */
+ private boolean hasInsetsAtDismissTarget(SnapTarget dismissTarget) {
+ if (isHorizontalDivision()) {
+ if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+ return mStableInsets.top != 0;
+ } else {
+ return mStableInsets.bottom != 0;
+ }
+ } else {
+ if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+ return mStableInsets.left != 0;
+ } else {
+ return mStableInsets.right != 0;
+ }
+ }
}
/**
@@ -587,7 +626,7 @@
}
if (dismissTarget != null && fraction > 0f
&& isDismissing(splitTarget, position, dockSide)) {
- fraction = calculateParallaxDismissingFraction(fraction);
+ fraction = calculateParallaxDismissingFraction(fraction, dockSide);
int offsetPosition = (int) (taskPosition +
fraction * (dismissTarget.position - splitTarget.position));
int width = taskRect.width();
@@ -617,8 +656,14 @@
* @return for a specified {@code fraction}, this returns an adjusted value that simulates a
* slowing down parallax effect
*/
- private static float calculateParallaxDismissingFraction(float fraction) {
- return SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+ private static float calculateParallaxDismissingFraction(float fraction, int dockSide) {
+ float result = SLOWDOWN_INTERPOLATOR.getInterpolation(fraction) / 3.5f;
+
+ // Less parallax at the top, just because.
+ if (dockSide == WindowManager.DOCKED_TOP) {
+ result /= 2f;
+ }
+ return result;
}
private static boolean isDismissing(SnapTarget snapTarget, int position, int dockSide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
new file mode 100644
index 0000000..f9afc7c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import android.content.Context;
+import android.content.DialogInterface;
+
+import com.android.systemui.R;
+
+public class UserUtil {
+ public static void deleteUserWithPrompt(Context context, int userId,
+ UserSwitcherController userSwitcherController) {
+ new RemoveUserDialog(context, userId, userSwitcherController).show();
+ }
+
+ private final static class RemoveUserDialog extends SystemUIDialog implements
+ DialogInterface.OnClickListener {
+
+ private final int mUserId;
+ private final UserSwitcherController mUserSwitcherController;
+
+ public RemoveUserDialog(Context context, int userId,
+ UserSwitcherController userSwitcherController) {
+ super(context);
+ setTitle(R.string.user_remove_user_title);
+ setMessage(context.getString(R.string.user_remove_user_message));
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ context.getString(android.R.string.cancel), this);
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(R.string.user_remove_user_remove), this);
+ setCanceledOnTouchOutside(false);
+ mUserId = userId;
+ mUserSwitcherController = userSwitcherController;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == BUTTON_NEGATIVE) {
+ cancel();
+ } else {
+ dismiss();
+ mUserSwitcherController.removeUserId(mUserId);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index 28f4e05..2294931 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.car;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -29,8 +28,8 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.statusbar.UserUtil;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
public class UserGridView extends GridView {
@@ -88,7 +87,8 @@
return true;
}
- new RemoveUserDialog(getContext(), record.info.id).show();
+ UserUtil.deleteUserWithPrompt(getContext(), record.info.id,
+ mUserSwitcherController);
return true;
}
});
@@ -159,32 +159,4 @@
return convertView;
}
}
-
- private final class RemoveUserDialog extends SystemUIDialog implements
- DialogInterface.OnClickListener {
-
- private final int mUserId;
-
- public RemoveUserDialog(Context context, int userId) {
- super(context);
- setTitle(R.string.user_remove_user_title);
- setMessage(context.getString(R.string.user_remove_user_message));
- setButton(DialogInterface.BUTTON_NEGATIVE,
- context.getString(android.R.string.cancel), this);
- setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(R.string.user_remove_user_remove), this);
- setCanceledOnTouchOutside(false);
- mUserId = userId;
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == BUTTON_NEGATIVE) {
- cancel();
- } else {
- dismiss();
- mUserSwitcherController.removeUserId(mUserId);
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 277668f..575eda7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -93,7 +93,7 @@
public static final long DOZE_ANIMATION_DURATION = 700;
private KeyguardAffordanceHelper mAfforanceHelper;
- private BaseStatusBarHeader mHeader;
+ protected BaseStatusBarHeader mHeader;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
private KeyguardStatusBarView mKeyguardStatusBar;
private QSContainer mQsContainer;
@@ -2404,7 +2404,7 @@
setVerticalPanelTranslation(0f);
}
- private void setVerticalPanelTranslation(float translation) {
+ protected void setVerticalPanelTranslation(float translation) {
mNotificationStackScroller.setTranslationX(translation);
mScrollView.setTranslationX(translation);
mHeader.setTranslationX(translation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 6d51869..07dc4fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -795,7 +795,7 @@
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
- // set the inital view visibility
+ // set the initial view visibility
setAreThereNotifications();
mIconController = new StatusBarIconController(
@@ -2339,8 +2339,6 @@
}
- Animator mScrollViewAnim, mClearButtonAnim;
-
@Override
public void animateExpandNotificationsPanel() {
if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index db901aa..29801b3 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -46,7 +46,6 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -86,6 +85,7 @@
import com.android.internal.widget.IRemoteViewsFactory;
import com.android.server.LocalServices;
import com.android.server.WidgetBackupProvider;
+import com.android.server.policy.IconUtilities;
import libcore.io.IoUtils;
@@ -104,6 +104,7 @@
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -155,9 +156,17 @@
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
onUserStopped(userId);
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- refreshProfileWidgetsMaskedState(userId);
+ reloadWidgetsMaskedStateForUser(userId);
} else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
- refreshWidgetMaskedState(userId);
+ synchronized (mLock) {
+ reloadWidgetQuietModeMaskedStateLocked(userId);
+ }
+ } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ updateWidgetPackageSuspensionMaskedState(packages, true, getSendingUserId());
+ } else if (Intent.ACTION_PACKAGES_UNSUSPENDED.equals(action)) {
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ updateWidgetPackageSuspensionMaskedState(packages, false, getSendingUserId());
} else {
onPackageBroadcastReceived(intent, userId);
}
@@ -206,6 +215,8 @@
private boolean mSafeMode;
private int mMaxWidgetBitmapMemory;
+ private final IconUtilities mIconUtilities;
+
AppWidgetServiceImpl(Context context) {
mContext = context;
mPackageManager = AppGlobals.getPackageManager();
@@ -216,6 +227,7 @@
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
mBackupRestoreController = new BackupRestoreController();
mSecurityPolicy = new SecurityPolicy();
+ mIconUtilities = new IconUtilities(context);
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
@@ -268,6 +280,12 @@
offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
offModeFilter, null, null);
+
+ IntentFilter suspendPackageFilter = new IntentFilter();
+ suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+ suspendPackageFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+ mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+ suspendPackageFilter, null, null);
}
private void registerOnCrossProfileProvidersChangedListener() {
@@ -413,15 +431,20 @@
}
/**
- * Refresh the masked state for all profiles under the given user.
+ * Reload all widgets' masked state for the given user and its associated profiles, including
+ * due to quiet mode and package suspension.
*/
- private void refreshProfileWidgetsMaskedState(int userId) {
+ private void reloadWidgetsMaskedStateForUser(int userId) {
if (!mUserManager.isUserUnlocked(userId)) return;
- List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
- if (profiles != null) {
- for (int i = 0; i < profiles.size(); i++) {
- UserInfo user = profiles.get(i);
- refreshWidgetMaskedState(user.id);
+ synchronized (mLock) {
+ reloadWidgetPackageSuspensionMaskedStateLocked(userId);
+ List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
+ if (profiles != null) {
+ for (int i = 0; i < profiles.size(); i++) {
+ UserInfo user = profiles.get(i);
+ reloadWidgetQuietModeMaskedStateLocked(user.id);
+ reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
+ }
}
}
}
@@ -429,7 +452,7 @@
/**
* Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
*/
- private void refreshWidgetMaskedState(int profileId) {
+ private void reloadWidgetQuietModeMaskedStateLocked(int profileId) {
if (!mUserManager.isUserUnlocked(profileId)) return;
final long identity = Binder.clearCallingIdentity();
try {
@@ -438,25 +461,18 @@
return;
}
boolean shouldMask = user.isQuietModeEnabled();
- final int iconSize = (int) mContext.getResources().getDimension(
- android.R.dimen.app_icon_size);
- synchronized (mLock) {
- final int N = mProviders.size();
- for (int i = 0; i < N; i++) {
- Provider provider = mProviders.get(i);
- int providerUserId = provider.getUserId();
- if (providerUserId == profileId) {
- final int widgetCount = provider.widgets.size();
- for (int j = 0; j < widgetCount; j++) {
- Widget widget = provider.widgets.get(j);
- if (shouldMask) {
- widget.replaceWithMaskedViewsLocked(mContext, iconSize);
- } else {
- widget.clearMaskedViewsLocked();
- }
- scheduleNotifyUpdateAppWidgetLocked(widget,
- widget.getEffectiveViewsLocked());
- }
+ final int N = mProviders.size();
+ for (int i = 0; i < N; i++) {
+ Provider provider = mProviders.get(i);
+ int providerUserId = provider.getUserId();
+ if (providerUserId != profileId) {
+ continue;
+ }
+ if (provider.setMaskedByQuietProfileLocked(shouldMask)) {
+ if (provider.isMaskedLocked()) {
+ maskWidgetsViewsLocked(provider);
+ } else {
+ unmaskWidgetsViewsLocked(provider);
}
}
}
@@ -465,6 +481,103 @@
}
}
+ /**
+ * Reload widget's masked state due to package suspension state.
+ */
+ private void reloadWidgetPackageSuspensionMaskedStateLocked(int profileId) {
+ final int N = mProviders.size();
+ for (int i = 0; i < N; i++) {
+ Provider provider = mProviders.get(i);
+ int providerUserId = provider.getUserId();
+ if (providerUserId != profileId) {
+ continue;
+ }
+ try {
+ ApplicationInfo ai = mPackageManager.getApplicationInfo(
+ provider.info.provider.getPackageName(), 0, provider.getUserId());
+ boolean suspended = (ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
+ if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
+ if (provider.isMaskedLocked()) {
+ maskWidgetsViewsLocked(provider);
+ } else {
+ unmaskWidgetsViewsLocked(provider);
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to query application info", e);
+ }
+ }
+ }
+
+ /**
+ * Incrementally update the masked state due to package suspension state.
+ */
+ private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
+ int profileId) {
+ if (packagesArray == null) {
+ return;
+ }
+ Set<String> packages = new ArraySet<String>(Arrays.asList(packagesArray));
+ synchronized (mLock) {
+ final int N = mProviders.size();
+ for (int i = 0; i < N; i++) {
+ Provider provider = mProviders.get(i);
+ int providerUserId = provider.getUserId();
+ if (providerUserId != profileId
+ || !packages.contains(provider.info.provider.getPackageName())) {
+ continue;
+ }
+ if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
+ if (provider.isMaskedLocked()) {
+ maskWidgetsViewsLocked(provider);
+ } else {
+ unmaskWidgetsViewsLocked(provider);
+ }
+ }
+ }
+ }
+ }
+
+ private void maskWidgetsViewsLocked(Provider provider) {
+ Bitmap iconBitmap = null;
+ try {
+ // Load the unbadged application icon and pass it to the widget to appear on
+ // the masked view.
+ final String providerPackage = provider.info.provider.getPackageName();
+ Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
+ UserHandle.of(provider.getUserId()));
+ PackageManager pm = userContext.getPackageManager();
+ Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
+ // Create a bitmap of the icon which is what the widget's remoteview requires.
+ iconBitmap = mIconUtilities.createIconBitmap(icon);
+ } catch (NameNotFoundException e) {
+ Slog.e(TAG, "Fail to get application icon", e);
+ // Provider package removed, no need to mask its views as its state will be
+ // purged very soon.
+ return;
+ }
+
+ final int widgetCount = provider.widgets.size();
+ for (int j = 0; j < widgetCount; j++) {
+ Widget widget = provider.widgets.get(j);
+ if (widget.replaceWithMaskedViewsLocked(mContext, iconBitmap)) {
+ scheduleNotifyUpdateAppWidgetLocked(widget,
+ widget.getEffectiveViewsLocked());
+ }
+ }
+ }
+
+ private void unmaskWidgetsViewsLocked(Provider provider) {
+ final int widgetCount = provider.widgets.size();
+ for (int j = 0; j < widgetCount; j++) {
+ Widget widget = provider.widgets.get(j);
+ if (widget.clearMaskedViewsLocked()) {
+ scheduleNotifyUpdateAppWidgetLocked(widget,
+ widget.getEffectiveViewsLocked());
+ }
+ }
+ }
+
private void resolveHostUidLocked(String pkg, int uid) {
final int N = mHosts.size();
for (int i = 0; i < N; i++) {
@@ -3442,6 +3555,9 @@
PendingIntent broadcast;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
+ boolean maskedByQuietProfile;
+ boolean maskedBySuspendedPackage;
+
int tag = TAG_UNDEFINED; // for use while saving state (the index)
public int getUserId() {
@@ -3470,6 +3586,24 @@
public String toString() {
return "Provider{" + id + (zombie ? " Z" : "") + '}';
}
+
+ // returns true if the provider's masked state is changed as a result
+ public boolean setMaskedByQuietProfileLocked(boolean masked) {
+ boolean oldMaskedState = isMaskedLocked();
+ maskedByQuietProfile = masked;
+ return isMaskedLocked() != oldMaskedState;
+ }
+
+ // returns true if the provider's masked state is changed as a result
+ public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
+ boolean oldMaskedState = isMaskedLocked();
+ maskedBySuspendedPackage = masked;
+ return isMaskedLocked() != oldMaskedState;
+ }
+
+ public boolean isMaskedLocked() {
+ return maskedByQuietProfile || maskedBySuspendedPackage;
+ }
}
private static final class ProviderId {
@@ -3625,28 +3759,24 @@
return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
}
- public void replaceWithMaskedViewsLocked(Context context, int iconSize) {
+ private boolean replaceWithMaskedViewsLocked(Context context, Bitmap icon) {
if (maskedViews != null) {
- return;
+ return false;
}
maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
- try {
- Drawable icon = context.getPackageManager().getApplicationIcon(
- provider.info.provider.getPackageName());
- final int width = iconSize;
- final int height = iconSize;
- Bitmap iconBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(iconBitmap);
- icon.setBounds(0, 0, width, height);
- icon.draw(canvas);
- maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, iconBitmap);
- } catch (NameNotFoundException e) {
- Slog.e(TAG, "Fail to get application icon", e);
+ if (icon != null) {
+ maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, icon);
}
+ return true;
}
- public void clearMaskedViewsLocked() {
- maskedViews = null;
+ private boolean clearMaskedViewsLocked() {
+ if (maskedViews != null) {
+ maskedViews = null;
+ return true;
+ } else {
+ return false;
+ }
}
public RemoteViews getEffectiveViewsLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 655950e..ba5bb39 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -249,6 +249,7 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
@@ -9344,6 +9345,10 @@
try {
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
+ if (stackId == DOCKED_STACK_ID) {
+ mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+ null /* initialBounds */);
+ }
mStackSupervisor.moveTaskToStackLocked(taskId, stackId, toTop, !FORCE_FOCUS,
"moveTaskToStack", ANIMATE);
} finally {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 4879cbfb..914776e 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -657,7 +657,6 @@
_intent.getCategories().size() == 1 &&
_intent.getData() == null &&
_intent.getType() == null &&
- (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
!isResolverActivity()) {
// This sure looks like a home activity!
mActivityType = HOME_ACTIVITY_TYPE;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 577ca48..0e970b3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1673,11 +1673,37 @@
TaskRecord task, ActivityRecord r) {
if (r.fullscreen) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
// At this point, nothing else needs to be shown in this task.
behindFullscreenActivity = true;
- } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
+ } else if (isHomeStack()) {
+ if (r.isHomeActivity()) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home activity: at " + r
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
+ // No other activity in the home stack should be visible behind the home activity.
+ // Home activities is usually a translucent activity with the wallpaper behind them.
+ // However, when they don't have the wallpaper behind them, we want to show
+ // activities in the next application stack behind them vs. another activity in the
+ // home stack like recents.
+ behindFullscreenActivity = true;
+ } else if (r.isRecentsActivity()
+ && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+ "Recents activity returning to app: at " + r
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
+ // We don't want any other activities in the home stack visible if the recents
+ // activity is going to be returning to an application activity type.
+ // We do this to preserve the visible order the user used to get into the recents
+ // activity. The recents activity is normally translucent and if it doesn't have
+ // the wallpaper behind it the next activity in the home stack shouldn't be visible
+ // when the home stack is brought to the front to display the recents activity from
+ // an app.
+ behindFullscreenActivity = true;
+ }
+ } else if (r.frontOfTask && task.isOverHomeStack()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r
+ " stackInvisible=" + stackInvisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 31712d9..c41caa8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1549,14 +1549,6 @@
mService.mUserController.finishUserSwitch(startingUsers.get(i));
}
}
- // Complete starting up of background users
- if (mStartingBackgroundUsers.size() > 0) {
- startingUsers = new ArrayList<UserState>(mStartingBackgroundUsers);
- mStartingBackgroundUsers.clear();
- for (int i = 0; i < startingUsers.size(); i++) {
- mService.mUserController.finishUserBoot(startingUsers.get(i));
- }
- }
}
mService.trimApplications();
@@ -2240,8 +2232,9 @@
}
final ActivityRecord topActivity = task.getTopActivity();
+ final int sourceStackId = task.stack != null ? task.stack.mStackId : INVALID_STACK_ID;
final boolean mightReplaceWindow =
- StackId.preserveWindowOnTaskMove(stackId) && topActivity != null;
+ StackId.replaceWindowsOnTaskMove(sourceStackId, stackId) && topActivity != null;
if (mightReplaceWindow) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
@@ -2263,15 +2256,19 @@
}
boolean kept = true;
+
+ // We might trigger a configuration change. Save the current task bounds for freezing.
+ mWindowManager.prepareFreezingTaskBounds(stack.mStackId);
+
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
- kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
+ kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID
&& task.mBounds == null && task.mLastNonFullscreenBounds != null) {
kept = resizeTaskLocked(task, task.mLastNonFullscreenBounds,
- RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
+ RESIZE_MODE_SYSTEM, !mightReplaceWindow);
} else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
- kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
+ kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
}
if (mightReplaceWindow) {
@@ -2283,7 +2280,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, !PRESERVE_WINDOWS);
+ ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
resumeFocusedStackTopActivityLocked();
showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
@@ -2765,15 +2762,6 @@
return homeInFront;
}
- /**
- * Add background users to send boot completed events to.
- * @param userId The user being started in the background
- * @param uss The state object for the user.
- */
- public void startBackgroundUserLocked(int userId, UserState uss) {
- mStartingBackgroundUsers.add(uss);
- }
-
/** Checks whether the userid is a profile of the current user. */
boolean isCurrentProfileLocked(int userId) {
if (userId == mCurrentUser) return true;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index b8d94eb..98eebea 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -48,6 +48,7 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.ANIMATE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -941,12 +942,8 @@
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- if (!mMovedHome
- && (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
- == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
- // Caller wants to appear on home activity, so before starting
- // their own activity we will bring home to the front.
- mStartActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+ if (!mMovedHome) {
+ updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
}
} else if (mSourceRecord != null) {
if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
@@ -1287,11 +1284,7 @@
mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;
}
- if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
- == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
- // Caller wants to appear on home activity.
- intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
- }
+ updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
mOptions = null;
}
}
@@ -1308,6 +1301,23 @@
return intentActivity;
}
+ private void updateTaskReturnToType(
+ TaskRecord task, int launchFlags, ActivityStack focusedStack) {
+ if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
+ == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
+ // Caller wants to appear on home activity.
+ task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+ return;
+ } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
+ // Task will be launched over the home stack, so return home.
+ task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+ return;
+ }
+
+ // Else we are coming from an application stack so return to an application.
+ task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+ }
+
private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 272f26f..f39ab2f 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -128,8 +128,6 @@
private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
- static final boolean IGNORE_RETURN_TO_RECENTS = true;
-
static final int INVALID_TASK_ID = -1;
final int taskId; // Unique identifier for this task.
@@ -459,8 +457,8 @@
}
void setTaskToReturnTo(int taskToReturnTo) {
- mTaskToReturnTo = (IGNORE_RETURN_TO_RECENTS && taskToReturnTo == RECENTS_ACTIVITY_TYPE)
- ? HOME_ACTIVITY_TYPE : taskToReturnTo;
+ mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
+ ? HOME_ACTIVITY_TYPE : taskToReturnTo;
}
int getTaskToReturnTo() {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a21570ce..551f332 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -202,11 +202,11 @@
}
}
- void finishUserBoot(UserState uss) {
+ private void finishUserBoot(UserState uss) {
finishUserBoot(uss, null);
}
- void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
+ private void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
final int userId = uss.mHandle.getIdentifier();
synchronized (mService) {
// Bail if we ended up with a stale user
@@ -711,7 +711,7 @@
moveUserToForegroundLocked(uss, oldUserId, userId);
}
} else {
- mService.mStackSupervisor.startBackgroundUserLocked(userId, uss);
+ mService.mUserController.finishUserBoot(uss);
}
if (needStart) {
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index 07903e9..c1a7ac6 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -107,11 +107,6 @@
}
@Override
- public void onRequestConditions(int relevance) {
- // by convention
- }
-
- @Override
public void onSubscribe(Uri conditionId) {
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
mTime = ZenModeConfig.tryParseCountdownConditionId(conditionId);
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index a4d5bce..ab3cb83 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -134,12 +134,6 @@
}
@Override
- public void onRequestConditions(int relevance) {
- if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
- // does not advertise conditions
- }
-
- @Override
public void onSubscribe(Uri conditionId) {
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
if (!ZenModeConfig.isValidEventConditionId(conditionId)) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8790415..ebdb1b2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2840,17 +2840,20 @@
final int N = mNotificationList.size();
ArrayList<String> orderBefore = new ArrayList<String>(N);
int[] visibilities = new int[N];
+ int [] importances = new int[N];
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
orderBefore.add(r.getKey());
visibilities[i] = r.getPackageVisibilityOverride();
+ importances[i] = r.getImportance();
mRankingHelper.extractSignals(r);
}
mRankingHelper.sort(mNotificationList);
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
if (!orderBefore.get(i).equals(r.getKey())
- || visibilities[i] != r.getPackageVisibilityOverride()) {
+ || visibilities[i] != r.getPackageVisibilityOverride()
+ || importances[i] != r.getImportance()) {
scheduleSendRankingUpdate();
return;
}
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 44448cc..c9b0ebb 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -107,12 +107,6 @@
}
@Override
- public void onRequestConditions(int relevance) {
- if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
- // does not advertise conditions
- }
-
- @Override
public void onSubscribe(Uri conditionId) {
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
if (!ZenModeConfig.isValidScheduleConditionId(conditionId)) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 87f505d..f11872e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -93,7 +93,8 @@
UserManager.DISALLOW_CAMERA,
UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_DATA_ROAMING,
- UserManager.DISALLOW_SET_USER_ICON
+ UserManager.DISALLOW_SET_USER_ICON,
+ UserManager.DISALLOW_SET_WALLPAPER
);
/**
diff --git a/services/core/java/com/android/server/policy/IconUtilities.java b/services/core/java/com/android/server/policy/IconUtilities.java
index 4658344..b196dec 100644
--- a/services/core/java/com/android/server/policy/IconUtilities.java
+++ b/services/core/java/com/android/server/policy/IconUtilities.java
@@ -37,7 +37,7 @@
/**
* Various utilities shared amongst the Launcher's classes.
*/
-final class IconUtilities {
+public final class IconUtilities {
private static final String TAG = "IconUtilities";
private static final int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
@@ -102,7 +102,7 @@
* Returns a bitmap suitable for the all apps view. The bitmap will be a power
* of two sized ARGB_8888 bitmap that can be used as a gl texture.
*/
- private Bitmap createIconBitmap(Drawable icon) {
+ public Bitmap createIconBitmap(Drawable icon) {
int width = mIconWidth;
int height = mIconHeight;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index c7d7096..09c53ae 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -27,6 +27,7 @@
import android.app.PendingIntent;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
+import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.backup.WallpaperBackupHelper;
import android.content.BroadcastReceiver;
@@ -84,6 +85,7 @@
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
@@ -611,7 +613,7 @@
return changed;
}
}
-
+
public WallpaperManagerService(Context context) {
if (DEBUG) Slog.v(TAG, "WallpaperService startup");
mContext = context;
@@ -626,7 +628,7 @@
getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
loadSettingsLocked(UserHandle.USER_SYSTEM);
}
-
+
private static File getWallpaperDir(int userId) {
return Environment.getUserSystemDirectory(userId);
}
@@ -764,7 +766,7 @@
public void clearWallpaper(String callingPackage) {
if (DEBUG) Slog.v(TAG, "clearWallpaper");
checkPermission(android.Manifest.permission.SET_WALLPAPER);
- if (!isWallpaperSupported(callingPackage)) {
+ if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
return;
}
synchronized (mLock) {
@@ -1000,7 +1002,7 @@
return null;
}
- if (!isWallpaperSupported(callingPackage)) {
+ if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
return null;
}
@@ -1069,7 +1071,7 @@
}
public void setWallpaperComponentChecked(ComponentName name, String callingPackage) {
- if (isWallpaperSupported(callingPackage)) {
+ if (isWallpaperSupported(callingPackage) && isWallpaperSettingAllowed(callingPackage)) {
setWallpaperComponent(name);
}
}
@@ -1093,7 +1095,7 @@
}
}
}
-
+
boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
@@ -1113,7 +1115,7 @@
}
}
}
-
+
try {
if (componentName == null) {
componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
@@ -1143,9 +1145,9 @@
Slog.w(TAG, msg);
return false;
}
-
+
WallpaperInfo wi = null;
-
+
Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
if (componentName != null && !componentName.equals(mImageWallpaper)) {
// Make sure the selected service is actually a wallpaper service.
@@ -1185,7 +1187,7 @@
return false;
}
}
-
+
// Bind the service!
if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
@@ -1314,6 +1316,23 @@
callingPackage) == AppOpsManager.MODE_ALLOWED;
}
+ @Override
+ public boolean isWallpaperSettingAllowed(String callingPackage) {
+ final PackageManager pm = mContext.getPackageManager();
+ String[] uidPackages = pm.getPackagesForUid(Binder.getCallingUid());
+ boolean uidMatchPackage = Arrays.asList(uidPackages).contains(callingPackage);
+ if (!uidMatchPackage) {
+ return false; // callingPackage was faked.
+ }
+
+ final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ if (dpm.isDeviceOwnerApp(callingPackage) || dpm.isProfileOwnerApp(callingPackage)) {
+ return true;
+ }
+ final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER);
+ }
+
private static JournaledFile makeJournaledFile(int userId) {
final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
return new JournaledFile(new File(base), new File(base + ".tmp"));
@@ -1465,7 +1484,7 @@
.getPackageName())) {
wallpaper.nextWallpaperComponent = mImageWallpaper;
}
-
+
if (DEBUG) {
Slog.v(TAG, "mWidth:" + wallpaper.width);
Slog.v(TAG, "mHeight:" + wallpaper.height);
@@ -1666,7 +1685,7 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
-
+
pw.println("Permission Denial: can't dump wallpaper service from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 43a17c9..1821487 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -483,6 +483,62 @@
* and inner rectangles.
*/
private static float computePivot(int startPos, float finalScale) {
+
+ /*
+ Theorem of intercepting lines:
+
+ + + +-----------------------------------------------+
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ x | y | | |
+ | | | |
+ | | | |
+ | | | |
+ | | | |
+ | + | +--------------------+ |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | | | |
+ | | +--------------------+ |
+ | | |
+ | | |
+ | | |
+ | | |
+ | | |
+ | | |
+ | | |
+ | +-----------------------------------------------+
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ + ++
+ p ++
+
+ scale = (x - y) / x
+ <=> x = -y / (scale - 1)
+ */
final float denom = finalScale-1;
if (Math.abs(denom) < .0001f) {
return startPos;
@@ -733,14 +789,14 @@
float unscaledHeight = thumbHeight * scaleW;
getNextAppTransitionStartRect(taskId, mTmpRect);
final float unscaledStartY = mTmpRect.top - (unscaledHeight - thumbHeight) / 2f;
- final float toY = appRect.top + mNextAppTransitionInsets.top + -unscaledStartY;
+ final float toY = appRect.top + -unscaledStartY;
if (mNextAppTransitionScaleUp) {
// Animation up from the thumbnail to the full screen
Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
mTmpRect.left + (thumbWidth / 2f), mTmpRect.top + (thumbHeight / 2f));
scale.setInterpolator(mTouchResponseInterpolator);
scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
- Animation alpha = new AlphaAnimation(1, 0);
+ Animation alpha = new AlphaAnimation(1f, 0f);
alpha.setInterpolator(mThumbnailFadeOutInterpolator);
alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
final float toX = appRect.left + appRect.width() / 2 -
@@ -809,35 +865,27 @@
containingFrame, surfaceInsets, taskId);
} else {
mTmpFromClipRect.set(containingFrame);
- // exclude top screen decor (status bar) region from the source clip.
- mTmpFromClipRect.top = contentInsets.top;
- // App window scaling up to become full screen
mTmpToClipRect.set(containingFrame);
- if (orientation == Configuration.ORIENTATION_PORTRAIT) {
- // In portrait, we scale the width and clip to the top/left square
- scale = thumbWidth / appWidth;
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbHeight = (int) (thumbHeight / scale);
- mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
- } else {
- // In landscape, we scale the height and clip to the top/left square. We
- // only scale the part that is not covered by status bar and the nav bar.
- scale = thumbHeight / (appHeight - contentInsets.top
- - contentInsets.bottom);
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbWidth = (int) (thumbWidth / scale);
- mTmpFromClipRect.right = mTmpFromClipRect.left + unscaledThumbWidth;
- // This removes the navigation bar from the first frame, so it better
- // matches the thumbnail. We need to do this explicitly in landscape,
- // because in portrait we already crop vertically.
- mTmpFromClipRect.bottom = mTmpFromClipRect.bottom - contentInsets.bottom;
- }
+
+ // Containing frame is in screen space, but we need the clip rect in the
+ // app space.
+ mTmpFromClipRect.offsetTo(0, 0);
+ mTmpToClipRect.offsetTo(0, 0);
+
+ // Exclude insets region from the source clip.
+ mTmpFromClipRect.inset(contentInsets);
+
+ // We scale the width and clip to the top/left square
+ scale = thumbWidth / (appWidth - contentInsets.left - contentInsets.right);
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
- computePivot(mTmpRect.left, scale),
- computePivot(mTmpRect.top, scale));
+ computePivot(mTmpRect.left - containingFrame.left, scale),
+ computePivot(mTmpRect.top - containingFrame.top, scale));
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
@@ -879,32 +927,26 @@
} else {
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
- // exclude top screen decor (status bar) region from the destination clip.
- mTmpToClipRect.top = contentInsets.top;
- if (orientation == Configuration.ORIENTATION_PORTRAIT) {
- // In portrait, we scale the width and clip to the top/left square
- scale = thumbWidth / appWidth;
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbHeight = (int) (thumbHeight / scale);
- mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
- } else {
- // In landscape, we scale the height and clip to the top/left square. We only
- // scale the part that is not covered by status bar and the nav bar.
- scale = thumbHeight / (appHeight - contentInsets.top - contentInsets.bottom);
- scaledTopDecor = (int) (scale * contentInsets.top);
- int unscaledThumbWidth = (int) (thumbWidth / scale);
- mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
- // This removes the navigation bar from the last frame, so it better matches the
- // thumbnail. We need to do this explicitly in landscape, because in portrait we
- // already crop vertically.
- mTmpToClipRect.bottom = mTmpToClipRect.bottom - contentInsets.bottom;
- }
+
+ // Containing frame is in screen space, but we need the clip rect in the
+ // app space.
+ mTmpFromClipRect.offsetTo(0, 0);
+ mTmpToClipRect.offsetTo(0, 0);
+
+ // Exclude insets region from the target clip.
+ mTmpToClipRect.inset(contentInsets);
+
+ // We scale the width and clip to the top/left square
+ scale = thumbWidth / (appWidth - contentInsets.left - contentInsets.right);
+ scaledTopDecor = (int) (scale * contentInsets.top);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
+ mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
- computePivot(mTmpRect.left, scale),
- computePivot(mTmpRect.top, scale));
+ computePivot(mTmpRect.left - containingFrame.left, scale),
+ computePivot(mTmpRect.top - containingFrame.top, scale));
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c542ff6..be1b85c 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -18,6 +18,7 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e7aba6d..47bdb5c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2980,9 +2980,7 @@
final Rect frame = new Rect(0, 0, width, height);
final Rect insets = new Rect();
Rect surfaceInsets = null;
- final boolean fullscreen = win != null && win.isFrameFullscreen(displayInfo);
final boolean freeform = win != null && win.inFreeformWorkspace();
- final boolean docked = win != null && win.inDockedWorkspace();
if (win != null) {
// Containing frame will usually cover the whole screen, including dialog windows.
// For freeform workspace windows it will not cover the whole screen and it also
@@ -2994,12 +2992,7 @@
frame.set(win.mContainingFrame);
}
surfaceInsets = win.getAttrs().surfaceInsets;
- if (fullscreen || docked) {
- // For fullscreen windows use the window frames and insets to set the thumbnail
- // clip. For non-fullscreen windows we use the app display region so the clip
- // isn't affected by the window insets.
- insets.set(win.mContentInsets);
- }
+ insets.set(win.mContentInsets);
}
if (atoken.mLaunchTaskBehind) {
@@ -3013,7 +3006,7 @@
+ " frame=" + frame + " insets=" + insets + " surfaceInsets=" + surfaceInsets);
Animation a = mAppTransition.loadAnimation(lp, transit, enter,
mCurConfiguration.orientation, frame, insets, surfaceInsets, isVoiceInteraction,
- !fullscreen, atoken.mTask.mTaskId);
+ freeform, atoken.mTask.mTaskId);
if (a != null) {
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
final int containingWidth = frame.width();
@@ -10389,6 +10382,14 @@
}
}
+ @Override
+ public void getStableInsets(Rect outInsets) throws RemoteException {
+ synchronized (mWindowMap) {
+ final DisplayInfo di = getDefaultDisplayInfoLocked();
+ mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
+ }
+ }
+
private final class LocalService extends WindowManagerInternal {
@Override
public void requestTraversalFromDisplayManager() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 4a9b356..465c7e0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -121,6 +121,8 @@
static final int DRAG_RESIZE_MODE_FREEFORM = 0;
static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1;
+ static final boolean DEBUG_DISABLE_SAVING_SURFACES = false;
+
final WindowManagerService mService;
final WindowManagerPolicy mPolicy;
final Context mContext;
@@ -1798,10 +1800,6 @@
return false;
}
- if (isChildWindow()) {
- return false;
- }
-
Task task = getTask();
if (task == null || task.inHomeStack()) {
// Don't save surfaces for home stack apps. These usually resume and draw
@@ -1815,6 +1813,10 @@
return false;
}
+ if (DEBUG_DISABLE_SAVING_SURFACES) {
+ return false;
+ }
+
return mAppToken.shouldSaveSurface();
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e904ad5..1dbca96 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1225,10 +1225,11 @@
calculateSurfaceBounds(w, w.getAttrs());
mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory);
+
+ mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale, mDtDx * w.mVScale,
+ mDsDy * w.mHScale, mDtDy * w.mVScale, recoveringMemory);
mSurfaceResized = mSurfaceController.setSizeInTransaction(
mTmpSize.width(), mTmpSize.height(),
- mDsDx * w.mHScale, mDtDx * w.mVScale,
- mDsDy * w.mHScale, mDtDy * w.mVScale,
recoveringMemory);
if (mSurfaceResized) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 5674ca2..e14cfdf 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -190,8 +190,27 @@
}
}
- boolean setSizeInTransaction(int width, int height, float dsdx, float dtdx, float dsdy, float dtdy,
+ void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
boolean recoveringMemory) {
+ try {
+ if (SHOW_TRANSACTIONS) logSurface(
+ "MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ mSurfaceControl.setMatrix(
+ dsdx, dtdx, dsdy, dtdy);
+ } catch (RuntimeException e) {
+ // If something goes wrong with the surface (such
+ // as running out of memory), don't take down the
+ // entire system.
+ Slog.e(TAG, "Error setting matrix on surface surface" + title
+ + " MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ if (!recoveringMemory) {
+ mAnimator.reclaimSomeSurfaceMemory("matrix", true);
+ }
+ }
+ return;
+ }
+
+ boolean setSizeInTransaction(int width, int height, boolean recoveringMemory) {
final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
if (surfaceResized) {
mSurfaceW = width;
@@ -201,8 +220,6 @@
if (SHOW_TRANSACTIONS) logSurface(
"SIZE " + width + "x" + height, null);
mSurfaceControl.setSize(width, height);
- mSurfaceControl.setMatrix(
- dsdx, dtdx, dsdy, dtdy);
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f2b36820..4022ac6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1459,6 +1459,10 @@
void settingsGlobalPutString(String name, String value) {
Settings.Global.putString(mContext.getContentResolver(), name, value);
}
+
+ void securityLogSetLoggingEnabledProperty(boolean enabled) {
+ SecurityLog.setLoggingEnabledProperty(enabled);
+ }
}
/**
@@ -8315,7 +8319,7 @@
private void disableDeviceLoggingIfNotCompliant() {
if (!isDeviceOwnerManagedSingleUserDevice()) {
- SecurityLog.setLoggingEnabledProperty(false);
+ mInjector.securityLogSetLoggingEnabledProperty(false);
Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
}
}
@@ -8326,7 +8330,7 @@
ensureDeviceOwnerManagingSingleUser(admin);
synchronized (this) {
- SecurityLog.setLoggingEnabledProperty(enabled);
+ mInjector.securityLogSetLoggingEnabledProperty(enabled);
if (enabled) {
mSecurityLogMonitor.start();
} else {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 90e4acf..bd37f4a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -281,5 +281,15 @@
void settingsGlobalPutString(String name, String value) {
context.settings.settingsGlobalPutString(name, value);
}
+
+ @Override
+ int settingsGlobalGetInt(String name, int def) {
+ return context.settings.settingsGlobalGetInt(name, def);
+ }
+
+ @Override
+ void securityLogSetLoggingEnabledProperty(boolean enabled) {
+ context.settings.securityLogSetLoggingEnabledProperty(enabled);
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 56667e5..6518732 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -191,6 +191,13 @@
void settingsGlobalPutString(String name, String value) {
}
+
+ int settingsGlobalGetInt(String name, int def) {
+ return 0;
+ }
+
+ void securityLogSetLoggingEnabledProperty(boolean enabled) {
+ }
}
public final Context realTestContext;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 597f915ec..354075e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -298,6 +298,10 @@
}
}
+ public ModuleProperties getModuleProperties() {
+ return moduleProperties;
+ }
+
//---- SoundTrigger.StatusListener methods
@Override
public void onRecognition(RecognitionEvent event) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
index 0a06bfa..7722876 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerInternal.java
@@ -44,9 +44,6 @@
public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
public static final int STATUS_OK = SoundTrigger.STATUS_OK;
- /** The {@link ModuleProperties} for the system, or null if none exists. */
- private ModuleProperties moduleProperties;
-
/**
* Starts recognition for the given keyphraseId.
*
@@ -76,9 +73,7 @@
*/
public abstract void stopAllRecognitions();
- public ModuleProperties getModuleProperties() {
- return moduleProperties;
- }
+ public abstract ModuleProperties getModuleProperties();
public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 5e8fe9e..682f4a4 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -23,6 +23,7 @@
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.os.Parcel;
import android.os.ParcelUuid;
@@ -180,6 +181,11 @@
}
@Override
+ public ModuleProperties getModuleProperties() {
+ return mSoundTriggerHelper.getModuleProperties();
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mSoundTriggerHelper.dump(fd, pw, args);
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 38eb5ee..2560c31 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -557,4 +557,8 @@
@Override
public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
}
+
+ @Override
+ public void getStableInsets(Rect outInsets) throws RemoteException {
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index a833ebe..4e4fcd0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -380,23 +380,17 @@
config.orientation = Configuration.ORIENTATION_UNDEFINED;
}
- try {
- ScreenRound roundness = hardwareConfig.getScreenRoundness();
- if (roundness != null) {
- switch (roundness) {
- case ROUND:
- config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
- break;
- case NOTROUND:
- config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO;
- }
- } else {
- config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED;
+ ScreenRound roundness = hardwareConfig.getScreenRoundness();
+ if (roundness != null) {
+ switch (roundness) {
+ case ROUND:
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
+ break;
+ case NOTROUND:
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO;
}
- } catch (NoSuchMethodError ignored) {
- // getScreenRoundness was added in later stages of API 15. So, it's not present on some
- // preview releases of API 15.
- // TODO: Remove the try catch around Oct 2015.
+ } else {
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED;
}
String locale = getParams().getLocale();
if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale);