diff options
68 files changed, 1250 insertions, 518 deletions
diff --git a/api/current.txt b/api/current.txt index fbda3c6..f1777db 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4179,6 +4179,7 @@ package android.app.admin { field public static final android.os.Parcelable.Creator CREATOR; field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7 field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8 + field public static final int USES_POLICY_DISABLE_KEYGUARD_WIDGETS = 9; // 0x9 field public static final int USES_POLICY_EXPIRE_PASSWORD = 6; // 0x6 field public static final int USES_POLICY_FORCE_LOCK = 3; // 0x3 field public static final int USES_POLICY_LIMIT_PASSWORD = 0; // 0x0 @@ -4214,6 +4215,7 @@ package android.app.admin { method public java.util.List<android.content.ComponentName> getActiveAdmins(); method public boolean getCameraDisabled(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); + method public int getKeyguardWidgetsDisabled(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); method public long getPasswordExpiration(android.content.ComponentName); @@ -4237,6 +4239,7 @@ package android.app.admin { method public void removeActiveAdmin(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); method public void setCameraDisabled(android.content.ComponentName, boolean); + method public void setKeyguardWidgetsDisabled(android.content.ComponentName, int); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); method public void setMaximumTimeToLock(android.content.ComponentName, long); method public void setPasswordExpirationTimeout(android.content.ComponentName, long); @@ -4260,6 +4263,8 @@ package android.app.admin { field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN"; + field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 2147483647; // 0x7fffffff + field public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0; // 0x0 field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000 field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000 field public static final int PASSWORD_QUALITY_BIOMETRIC_WEAK = 32768; // 0x8000 @@ -6250,6 +6255,7 @@ package android.content.pm { field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000 field public static final int CONFIG_KEYBOARD = 16; // 0x10 field public static final int CONFIG_KEYBOARD_HIDDEN = 32; // 0x20 + field public static final int CONFIG_LAYOUT_DIRECTION = 8192; // 0x2000 field public static final int CONFIG_LOCALE = 4; // 0x4 field public static final int CONFIG_MCC = 1; // 0x1 field public static final int CONFIG_MNC = 2; // 0x2 @@ -6852,9 +6858,12 @@ package android.content.res { method public int describeContents(); method public int diff(android.content.res.Configuration); method public boolean equals(android.content.res.Configuration); + method public int getLayoutDirection(); method public boolean isLayoutSizeAtLeast(int); method public static boolean needNewResources(int, int); method public void readFromParcel(android.os.Parcel); + method public void setLayoutDirection(java.util.Locale); + method public void setLocale(java.util.Locale); method public void setTo(android.content.res.Configuration); method public void setToDefaults(); method public int updateFrom(android.content.res.Configuration); @@ -6883,6 +6892,11 @@ package android.content.res { field public static final int ORIENTATION_PORTRAIT = 1; // 0x1 field public static final deprecated int ORIENTATION_SQUARE = 3; // 0x3 field public static final int ORIENTATION_UNDEFINED = 0; // 0x0 + field public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 64; // 0x40 + field public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 192; // 0xc0 + field public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 128; // 0x80 + field public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; // 0x6 + field public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0; // 0x0 field public static final int SCREENLAYOUT_LONG_MASK = 48; // 0x30 field public static final int SCREENLAYOUT_LONG_NO = 16; // 0x10 field public static final int SCREENLAYOUT_LONG_UNDEFINED = 0; // 0x0 @@ -6893,6 +6907,7 @@ package android.content.res { field public static final int SCREENLAYOUT_SIZE_SMALL = 1; // 0x1 field public static final int SCREENLAYOUT_SIZE_UNDEFINED = 0; // 0x0 field public static final int SCREENLAYOUT_SIZE_XLARGE = 4; // 0x4 + field public static final int SCREENLAYOUT_UNDEFINED = 0; // 0x0 field public static final int SCREEN_HEIGHT_DP_UNDEFINED = 0; // 0x0 field public static final int SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0 field public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0; // 0x0 diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index 7f3dbe5..bcd4588 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -1181,12 +1181,12 @@ public class Am { private class IntentReceiver extends IIntentReceiver.Stub { private boolean mFinished = false; - public synchronized void performReceive( - Intent intent, int rc, String data, Bundle ext, boolean ord, - boolean sticky) { - String line = "Broadcast completed: result=" + rc; + @Override + public void performReceive(Intent intent, int resultCode, String data, Bundle extras, + boolean ordered, boolean sticky, int sendingUser) throws RemoteException { + String line = "Broadcast completed: result=" + resultCode; if (data != null) line = line + ", data=\"" + data + "\""; - if (ext != null) line = line + ", extras: " + ext; + if (extras != null) line = line + ", extras: " + extras; System.out.println(line); mFinished = true; notifyAll(); diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c index ab64747..9e83a67 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.c @@ -14,6 +14,7 @@ ** limitations under the License. */ +#include <linux/capability.h> #include "installd.h" #include <diskusage/dirsize.h> @@ -665,16 +666,16 @@ int dexopt(const char *apk_path, uid_t uid, int is_public) ALOGE("dexopt cannot open '%s' for output\n", dex_path); goto fail; } - if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { - ALOGE("dexopt cannot chown '%s'\n", dex_path); - goto fail; - } if (fchmod(odex_fd, S_IRUSR|S_IWUSR|S_IRGRP | (is_public ? S_IROTH : 0)) < 0) { ALOGE("dexopt cannot chmod '%s'\n", dex_path); goto fail; } + if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { + ALOGE("dexopt cannot chown '%s'\n", dex_path); + goto fail; + } ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path); @@ -690,13 +691,23 @@ int dexopt(const char *apk_path, uid_t uid, int is_public) ALOGE("setuid(%d) during dexopt\n", uid); exit(65); } + // drop capabilities + struct __user_cap_header_struct capheader; + struct __user_cap_data_struct capdata[2]; + memset(&capheader, 0, sizeof(capheader)); + memset(&capdata, 0, sizeof(capdata)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + if (capset(&capheader, &capdata[0]) < 0) { + ALOGE("capset failed: %s\n", strerror(errno)); + exit(66); + } if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) { ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno)); - exit(66); + exit(67); } run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags); - exit(67); /* only get here on exec failure */ + exit(68); /* only get here on exec failure */ } else { res = wait_dexopt(pid, apk_path); if (res != 0) { diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c index d559639..652543fd 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.c @@ -14,6 +14,9 @@ ** limitations under the License. */ +#include <linux/capability.h> +#include <linux/prctl.h> + #include "installd.h" @@ -491,12 +494,53 @@ fail: return res; } +static void drop_privileges() { + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); + exit(1); + } + + if (setgid(AID_INSTALL) < 0) { + ALOGE("setgid() can't drop privileges; exiting.\n"); + exit(1); + } + + if (setuid(AID_INSTALL) < 0) { + ALOGE("setuid() can't drop privileges; exiting.\n"); + exit(1); + } + + struct __user_cap_header_struct capheader; + struct __user_cap_data_struct capdata[2]; + memset(&capheader, 0, sizeof(capheader)); + memset(&capdata, 0, sizeof(capdata)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; + + capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE); + capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN); + capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); + capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); + + capdata[0].effective = capdata[0].permitted; + capdata[1].effective = capdata[1].permitted; + capdata[0].inheritable = 0; + capdata[1].inheritable = 0; + + if (capset(&capheader, &capdata[0]) < 0) { + ALOGE("capset failed: %s\n", strerror(errno)); + exit(1); + } +} + int main(const int argc, const char *argv[]) { char buf[BUFFER_MAX]; struct sockaddr addr; socklen_t alen; int lsocket, s, count; + ALOGI("installd firing up\n"); + if (initialize_globals() < 0) { ALOGE("Could not initialize globals; exiting.\n"); exit(1); @@ -507,6 +551,8 @@ int main(const int argc, const char *argv[]) { exit(1); } + drop_privileges(); + lsocket = android_get_control_socket(SOCKET_PATH); if (lsocket < 0) { ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 14ba537..eed9254 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -300,7 +300,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM = b != null ? IIntentReceiver.Stub.asInterface(b) : null; IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data); String perm = data.readString(); - Intent intent = registerReceiver(app, packageName, rec, filter, perm); + int userId = data.readInt(); + Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId); reply.writeNoException(); if (intent != null) { reply.writeInt(1); @@ -1999,7 +2000,7 @@ class ActivityManagerProxy implements IActivityManager } public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, - IntentFilter filter, String perm) throws RemoteException + IntentFilter filter, String perm, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2009,6 +2010,7 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); filter.writeToParcel(data, 0); data.writeString(perm); + data.writeInt(userId); mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0); reply.readException(); Intent intent = null; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 1b788c2..97dcec0 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -320,8 +320,9 @@ public final class ActivityThread { static final class ReceiverData extends BroadcastReceiver.PendingResult { public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, - boolean ordered, boolean sticky, IBinder token) { - super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token); + boolean ordered, boolean sticky, IBinder token, int sendingUser) { + super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, + token, sendingUser); this.intent = intent; } @@ -613,9 +614,9 @@ public final class ActivityThread { public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, - boolean sync) { + boolean sync, int sendingUser) { ReceiverData r = new ReceiverData(intent, resultCode, data, extras, - sync, false, mAppThread.asBinder()); + sync, false, mAppThread.asBinder(), sendingUser); r.info = info; r.compatInfo = compatInfo; queueOrSendMessage(H.RECEIVER, r); @@ -774,8 +775,9 @@ public final class ActivityThread { // applies transaction ordering per object for such calls. public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, - boolean sticky) throws RemoteException { - receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky); + boolean sticky, int sendingUser) throws RemoteException { + receiver.performReceive(intent, resultCode, dataStr, extras, ordered, + sticky, sendingUser); } public void scheduleLowMemory() { diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 8e6278d..63aa5f9 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -193,8 +193,9 @@ public abstract class ApplicationThreadNative extends Binder String resultData = data.readString(); Bundle resultExtras = data.readBundle(); boolean sync = data.readInt() != 0; + int sendingUser = data.readInt(); scheduleReceiver(intent, info, compatInfo, resultCode, resultData, - resultExtras, sync); + resultExtras, sync, sendingUser); return true; } @@ -378,8 +379,9 @@ public abstract class ApplicationThreadNative extends Binder Bundle extras = data.readBundle(); boolean ordered = data.readInt() != 0; boolean sticky = data.readInt() != 0; + int sendingUser = data.readInt(); scheduleRegisteredReceiver(receiver, intent, - resultCode, dataStr, extras, ordered, sticky); + resultCode, dataStr, extras, ordered, sticky, sendingUser); return true; } @@ -755,7 +757,7 @@ class ApplicationThreadProxy implements IApplicationThread { public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String resultData, - Bundle map, boolean sync) throws RemoteException { + Bundle map, boolean sync, int sendingUser) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data, 0); @@ -765,6 +767,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeString(resultData); data.writeBundle(map); data.writeInt(sync ? 1 : 0); + data.writeInt(sendingUser); mRemote.transact(SCHEDULE_RECEIVER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); @@ -991,8 +994,8 @@ class ApplicationThreadProxy implements IApplicationThread { } public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, - int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky) - throws RemoteException { + int resultCode, String dataStr, Bundle extras, boolean ordered, + boolean sticky, int sendingUser) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(receiver.asBinder()); @@ -1002,6 +1005,7 @@ class ApplicationThreadProxy implements IApplicationThread { data.writeBundle(extras); data.writeInt(ordered ? 1 : 0); data.writeInt(sticky ? 1 : 0); + data.writeInt(sendingUser); mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 232ca07..65ea6a0 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -138,6 +138,17 @@ class ReceiverRestrictedContext extends ContextWrapper { } @Override + public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + throw new ReceiverCallNotAllowedException( + "IntentReceiver components are not allowed to register to receive intents"); + //ex.fillInStackTrace(); + //Log.e("IntentReceiver", ex.getMessage(), ex); + //return mContext.registerReceiver(receiver, filter, broadcastPermission, + // scheduler); + } + + @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { throw new ReceiverCallNotAllowedException( "IntentReceiver components are not allowed to bind to services"); @@ -1252,11 +1263,18 @@ class ContextImpl extends Context { @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { - return registerReceiverInternal(receiver, filter, broadcastPermission, - scheduler, getOuterContext()); + return registerReceiverInternal(receiver, UserHandle.myUserId(), + filter, broadcastPermission, scheduler, getOuterContext()); + } + + @Override + public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + return registerReceiverInternal(receiver, user.getIdentifier(), + filter, broadcastPermission, scheduler, getOuterContext()); } - private Intent registerReceiverInternal(BroadcastReceiver receiver, + private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; @@ -1279,7 +1297,7 @@ class ContextImpl extends Context { try { return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, - rd, filter, broadcastPermission); + rd, filter, broadcastPermission, userId); } catch (RemoteException e) { return null; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index f7c7013..7a633ed 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -80,7 +80,7 @@ public interface IActivityManager extends IInterface { public boolean willActivityBeVisible(IBinder token) throws RemoteException; public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, - String requiredPermission) throws RemoteException; + String requiredPermission, int userId) throws RemoteException; public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException; public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index f60cfd6..03a26d4 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -65,7 +65,8 @@ public interface IApplicationThread extends IInterface { void scheduleDestroyActivity(IBinder token, boolean finished, int configChanges) throws RemoteException; void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, - int resultCode, String data, Bundle extras, boolean sync) throws RemoteException; + int resultCode, String data, Bundle extras, boolean sync, + int sendingUser) throws RemoteException; static final int BACKUP_MODE_INCREMENTAL = 0; static final int BACKUP_MODE_FULL = 1; static final int BACKUP_MODE_RESTORE = 2; @@ -105,8 +106,8 @@ public interface IApplicationThread extends IInterface { void dumpProvider(FileDescriptor fd, IBinder servicetoken, String[] args) throws RemoteException; void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, - int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) - throws RemoteException; + int resultCode, String data, Bundle extras, boolean ordered, + boolean sticky, int sendingUser) throws RemoteException; void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException; void profilerControl(boolean start, String path, ParcelFileDescriptor fd, int profileType) diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 6197b1a..0a9ed58 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -670,8 +670,8 @@ public final class LoadedApk { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null; } - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered, boolean sticky) { + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean ordered, boolean sticky, int sendingUser) { LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); @@ -680,7 +680,7 @@ public final class LoadedApk { } if (rd != null) { rd.performReceive(intent, resultCode, data, extras, - ordered, sticky); + ordered, sticky, sendingUser); } else { // The activity manager dispatched a broadcast to a registered // receiver in this process, but before it could be delivered the @@ -716,10 +716,10 @@ public final class LoadedApk { private final boolean mOrdered; public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, - boolean ordered, boolean sticky) { + boolean ordered, boolean sticky, int sendingUser) { super(resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, - ordered, sticky, mIIntentReceiver.asBinder()); + ordered, sticky, mIIntentReceiver.asBinder(), sendingUser); mCurIntent = intent; mOrdered = ordered; } @@ -830,14 +830,15 @@ public final class LoadedApk { return mUnregisterLocation; } - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered, boolean sticky) { + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean ordered, boolean sticky, int sendingUser) { if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq + " to " + mReceiver); } - Args args = new Args(intent, resultCode, data, extras, ordered, sticky); + Args args = new Args(intent, resultCode, data, extras, ordered, + sticky, sendingUser); if (!mActivityThread.post(args)) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index bcd42ea..a3c1838 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -147,8 +147,8 @@ public final class PendingIntent implements Parcelable { mWho = who; mHandler = handler; } - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean serialized, boolean sticky) { + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean serialized, boolean sticky, int sendingUser) { mIntent = intent; mResultCode = resultCode; mResultData = data; diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java index 1c37414..c8062ca 100644 --- a/core/java/android/app/admin/DeviceAdminInfo.java +++ b/core/java/android/app/admin/DeviceAdminInfo.java @@ -50,23 +50,23 @@ import java.util.HashMap; */ public final class DeviceAdminInfo implements Parcelable { static final String TAG = "DeviceAdminInfo"; - + /** * A type of policy that this device admin can use: limit the passwords * that the user can select, via {@link DevicePolicyManager#setPasswordQuality} * and {@link DevicePolicyManager#setPasswordMinimumLength}. - * + * * <p>To control this policy, the device admin must have a "limit-password" * tag in the "uses-policies" section of its meta-data. */ public static final int USES_POLICY_LIMIT_PASSWORD = 0; - + /** * A type of policy that this device admin can use: able to watch login * attempts from the user, via {@link DeviceAdminReceiver#ACTION_PASSWORD_FAILED}, * {@link DeviceAdminReceiver#ACTION_PASSWORD_SUCCEEDED}, and * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts}. - * + * * <p>To control this policy, the device admin must have a "watch-login" * tag in the "uses-policies" section of its meta-data. */ @@ -76,7 +76,7 @@ public final class DeviceAdminInfo implements Parcelable { * A type of policy that this device admin can use: able to reset the * user's password via * {@link DevicePolicyManager#resetPassword}. - * + * * <p>To control this policy, the device admin must have a "reset-password" * tag in the "uses-policies" section of its meta-data. */ @@ -87,7 +87,7 @@ public final class DeviceAdminInfo implements Parcelable { * to lock via{@link DevicePolicyManager#lockNow} or limit the * maximum lock timeout for the device via * {@link DevicePolicyManager#setMaximumTimeToLock}. - * + * * <p>To control this policy, the device admin must have a "force-lock" * tag in the "uses-policies" section of its meta-data. */ @@ -97,7 +97,7 @@ public final class DeviceAdminInfo implements Parcelable { * A type of policy that this device admin can use: able to factory * reset the device, erasing all of the user's data, via * {@link DevicePolicyManager#wipeData}. - * + * * <p>To control this policy, the device admin must have a "wipe-data" * tag in the "uses-policies" section of its meta-data. */ @@ -138,13 +138,21 @@ public final class DeviceAdminInfo implements Parcelable { */ public static final int USES_POLICY_DISABLE_CAMERA = 8; + /** + * A type of policy that this device admin can use: disables use of keyguard widgets. + * + * <p>To control this policy, the device admin must have a "disable-keyguard-widgets" + * tag in the "uses-policies" section of its meta-data. + */ + public static final int USES_POLICY_DISABLE_KEYGUARD_WIDGETS = 9; + /** @hide */ public static class PolicyInfo { public final int ident; final public String tag; final public int label; final public int description; - + public PolicyInfo(int identIn, String tagIn, int labelIn, int descriptionIn) { ident = identIn; tag = tagIn; @@ -152,11 +160,11 @@ public final class DeviceAdminInfo implements Parcelable { description = descriptionIn; } } - + static ArrayList<PolicyInfo> sPoliciesDisplayOrder = new ArrayList<PolicyInfo>(); static HashMap<String, Integer> sKnownPolicies = new HashMap<String, Integer>(); static SparseArray<PolicyInfo> sRevKnownPolicies = new SparseArray<PolicyInfo>(); - + static { sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WIPE_DATA, "wipe-data", com.android.internal.R.string.policylab_wipeData, @@ -185,6 +193,10 @@ public final class DeviceAdminInfo implements Parcelable { sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_DISABLE_CAMERA, "disable-camera", com.android.internal.R.string.policylab_disableCamera, com.android.internal.R.string.policydesc_disableCamera)); + sPoliciesDisplayOrder.add(new PolicyInfo( + USES_POLICY_DISABLE_KEYGUARD_WIDGETS, "disable-keyguard-widgets", + com.android.internal.R.string.policylab_disableKeyguardWidgets, + com.android.internal.R.string.policydesc_disableKeyguardWidgets)); for (int i=0; i<sPoliciesDisplayOrder.size(); i++) { PolicyInfo pi = sPoliciesDisplayOrder.get(i); @@ -192,25 +204,25 @@ public final class DeviceAdminInfo implements Parcelable { sKnownPolicies.put(pi.tag, pi.ident); } } - + /** * The BroadcastReceiver that implements this device admin component. */ final ResolveInfo mReceiver; - + /** * Whether this should be visible to the user. */ boolean mVisible; - + /** * The policies this administrator needs access to. */ int mUsesPolicies; - + /** * Constructor. - * + * * @param context The Context in which we are parsing the device admin. * @param receiver The ResolveInfo returned from the package manager about * this device admin's component. @@ -219,9 +231,9 @@ public final class DeviceAdminInfo implements Parcelable { throws XmlPullParserException, IOException { mReceiver = receiver; ActivityInfo ai = receiver.activityInfo; - + PackageManager pm = context.getPackageManager(); - + XmlResourceParser parser = null; try { parser = ai.loadXmlMetaData(pm, DeviceAdminReceiver.DEVICE_ADMIN_META_DATA); @@ -229,30 +241,30 @@ public final class DeviceAdminInfo implements Parcelable { throw new XmlPullParserException("No " + DeviceAdminReceiver.DEVICE_ADMIN_META_DATA + " meta-data"); } - + Resources res = pm.getResourcesForApplication(ai.applicationInfo); - + AttributeSet attrs = Xml.asAttributeSet(parser); - + int type; while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { } - + String nodeName = parser.getName(); if (!"device-admin".equals(nodeName)) { throw new XmlPullParserException( "Meta-data does not start with device-admin tag"); } - + TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.DeviceAdmin); mVisible = sa.getBoolean( com.android.internal.R.styleable.DeviceAdmin_visible, true); - + sa.recycle(); - + int outerDepth = parser.getDepth(); while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -290,14 +302,14 @@ public final class DeviceAdminInfo implements Parcelable { mReceiver = ResolveInfo.CREATOR.createFromParcel(source); mUsesPolicies = source.readInt(); } - + /** * Return the .apk package that implements this device admin. */ public String getPackageName() { return mReceiver.activityInfo.packageName; } - + /** * Return the class name of the receiver component that implements * this device admin. @@ -321,20 +333,20 @@ public final class DeviceAdminInfo implements Parcelable { return new ComponentName(mReceiver.activityInfo.packageName, mReceiver.activityInfo.name); } - + /** * Load the user-displayed label for this device admin. - * + * * @param pm Supply a PackageManager used to load the device admin's * resources. */ public CharSequence loadLabel(PackageManager pm) { return mReceiver.loadLabel(pm); } - + /** * Load user-visible description associated with this device admin. - * + * * @param pm Supply a PackageManager used to load the device admin's * resources. */ @@ -351,17 +363,17 @@ public final class DeviceAdminInfo implements Parcelable { } throw new NotFoundException(); } - + /** * Load the user-displayed icon for this device admin. - * + * * @param pm Supply a PackageManager used to load the device admin's * resources. */ public Drawable loadIcon(PackageManager pm) { return mReceiver.loadIcon(pm); } - + /** * Returns whether this device admin would like to be visible to the * user, even when it is not enabled. @@ -369,7 +381,7 @@ public final class DeviceAdminInfo implements Parcelable { public boolean isVisible() { return mVisible; } - + /** * Return true if the device admin has requested that it be able to use * the given policy control. The possible policy identifier inputs are: @@ -382,7 +394,7 @@ public final class DeviceAdminInfo implements Parcelable { public boolean usesPolicy(int policyIdent) { return (mUsesPolicies & (1<<policyIdent)) != 0; } - + /** * Return the XML tag name for the given policy identifier. Valid identifiers * are as per {@link #usesPolicy(int)}. If the given identifier is not @@ -391,7 +403,7 @@ public final class DeviceAdminInfo implements Parcelable { public String getTagForPolicy(int policyIdent) { return sRevKnownPolicies.get(policyIdent).tag; } - + /** @hide */ public ArrayList<PolicyInfo> getUsedPolicies() { ArrayList<PolicyInfo> res = new ArrayList<PolicyInfo>(); @@ -403,25 +415,25 @@ public final class DeviceAdminInfo implements Parcelable { } return res; } - + /** @hide */ public void writePoliciesToXml(XmlSerializer out) throws IllegalArgumentException, IllegalStateException, IOException { out.attribute(null, "flags", Integer.toString(mUsesPolicies)); } - + /** @hide */ public void readPoliciesFromXml(XmlPullParser parser) throws XmlPullParserException, IOException { mUsesPolicies = Integer.parseInt( parser.getAttributeValue(null, "flags")); } - + public void dump(Printer pw, String prefix) { pw.println(prefix + "Receiver:"); mReceiver.dump(pw, prefix + " "); } - + @Override public String toString() { return "DeviceAdminInfo{" + mReceiver.activityInfo.name + "}"; @@ -429,7 +441,7 @@ public final class DeviceAdminInfo implements Parcelable { /** * Used to package this object into a {@link Parcel}. - * + * * @param dest The {@link Parcel} to be written. * @param flags The flags used for parceling. */ diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 0b58396..4c55bb3 100755 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1155,6 +1155,16 @@ public class DevicePolicyManager { = "android.app.action.START_ENCRYPTION"; /** + * Widgets are enabled in keyguard + */ + public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0; + + /** + * Disable all keyguard widgets + */ + public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 0x7fffffff; + + /** * Called by an application that is administering the device to * request that the storage system be encrypted. * @@ -1284,6 +1294,46 @@ public class DevicePolicyManager { } /** + * Called by an application that is administering the device to disable adding widgets to + * keyguard. After setting this, keyguard widgets will be disabled according to the state + * provided. + * + * <p>The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_WIDGETS} to be able to call + * this method; if it has not, a security exception will be thrown. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param which {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_ALL} or + * {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_NONE} (the default). + */ + public void setKeyguardWidgetsDisabled(ComponentName admin, int which) { + if (mService != null) { + try { + mService.setKeyguardWidgetsDisabled(admin, which); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } + + /** + * Determine whether or not widgets have been disabled in keyguard either by the current + * admin, if specified, or all admins. + * @param admin The name of the admin component to check, or null to check if any admins + * have disabled widgets in keyguard. + */ + public int getKeyguardWidgetsDisabled(ComponentName admin) { + if (mService != null) { + try { + return mService.getKeyguardWidgetsDisabled(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return KEYGUARD_DISABLE_WIDGETS_NONE; + } + + /** * @hide */ public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 9419a62..0b7ec12 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -48,7 +48,7 @@ interface IDevicePolicyManager { void setPasswordMinimumNonLetter(in ComponentName who, int length); int getPasswordMinimumNonLetter(in ComponentName who); - + void setPasswordHistoryLength(in ComponentName who, int length); int getPasswordHistoryLength(in ComponentName who); @@ -59,17 +59,17 @@ interface IDevicePolicyManager { boolean isActivePasswordSufficient(); int getCurrentFailedPasswordAttempts(); - + void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num); int getMaximumFailedPasswordsForWipe(in ComponentName admin); - + boolean resetPassword(String password, int flags); - + void setMaximumTimeToLock(in ComponentName who, long timeMs); long getMaximumTimeToLock(in ComponentName who); - + void lockNow(); - + void wipeData(int flags); ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList); @@ -82,6 +82,9 @@ interface IDevicePolicyManager { void setCameraDisabled(in ComponentName who, boolean disabled); boolean getCameraDisabled(in ComponentName who); + void setKeyguardWidgetsDisabled(in ComponentName who, int which); + int getKeyguardWidgetsDisabled(in ComponentName who); + void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing); boolean isAdminActive(in ComponentName policyReceiver); List<ComponentName> getActiveAdmins(); @@ -89,7 +92,7 @@ interface IDevicePolicyManager { void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); void removeActiveAdmin(in ComponentName policyReceiver); boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy); - + void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols, int nonletter); void reportFailedPasswordAttempt(); diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index 446f1af..1500b00 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -237,16 +237,17 @@ public abstract class BroadcastReceiver { final boolean mOrderedHint; final boolean mInitialStickyHint; final IBinder mToken; + final int mSendingUser; int mResultCode; String mResultData; Bundle mResultExtras; boolean mAbortBroadcast; boolean mFinished; - + /** @hide */ public PendingResult(int resultCode, String resultData, Bundle resultExtras, - int type, boolean ordered, boolean sticky, IBinder token) { + int type, boolean ordered, boolean sticky, IBinder token, int userId) { mResultCode = resultCode; mResultData = resultData; mResultExtras = resultExtras; @@ -254,6 +255,7 @@ public abstract class BroadcastReceiver { mOrderedHint = ordered; mInitialStickyHint = sticky; mToken = token; + mSendingUser = userId; } /** @@ -425,7 +427,12 @@ public abstract class BroadcastReceiver { } } } - + + /** @hide */ + public int getSendingUserId() { + return mSendingUser; + } + void checkSynchronousHint() { // Note that we don't assert when receiving the initial sticky value, // since that may have come from an ordered broadcast. We'll catch @@ -733,6 +740,11 @@ public abstract class BroadcastReceiver { return mPendingResult; } + /** @hide */ + public int getSendingUserId() { + return mPendingResult.mSendingUser; + } + /** * Control inclusion of debugging help for mismatched * calls to {@link Context#registerReceiver(BroadcastReceiver, IntentFilter) diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 8a4cb44..7438ba8 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1410,9 +1410,35 @@ public abstract class Context { * @see #unregisterReceiver */ public abstract Intent registerReceiver(BroadcastReceiver receiver, - IntentFilter filter, - String broadcastPermission, - Handler scheduler); + IntentFilter filter, String broadcastPermission, Handler scheduler); + + /** + * @hide + * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) + * but for a specific user. This receiver will receiver broadcasts that + * are sent to the requested user. It + * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} + * permission. + * + * @param receiver The BroadcastReceiver to handle the broadcast. + * @param user UserHandle to send the intent to. + * @param filter Selects the Intent broadcasts to be received. + * @param broadcastPermission String naming a permissions that a + * broadcaster must hold in order to send an Intent to you. If null, + * no permission is required. + * @param scheduler Handler identifying the thread that will receive + * the Intent. If null, the main thread of the process will be used. + * + * @return The first sticky intent found that matches <var>filter</var>, + * or null if there are none. + * + * @see #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler + * @see #sendBroadcast + * @see #unregisterReceiver + */ + public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver, + UserHandle user, IntentFilter filter, String broadcastPermission, + Handler scheduler); /** * Unregister a previously registered BroadcastReceiver. <em>All</em> diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index e8c63d6..6101f4e 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -425,6 +425,15 @@ public class ContextWrapper extends Context { scheduler); } + /** @hide */ + @Override + public Intent registerReceiverAsUser( + BroadcastReceiver receiver, UserHandle user, IntentFilter filter, + String broadcastPermission, Handler scheduler) { + return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission, + scheduler); + } + @Override public void unregisterReceiver(BroadcastReceiver receiver) { mBase.unregisterReceiver(receiver); diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl index 6f2f7c4..3d92723 100755 --- a/core/java/android/content/IIntentReceiver.aidl +++ b/core/java/android/content/IIntentReceiver.aidl @@ -27,7 +27,7 @@ import android.os.Bundle; * {@hide} */ oneway interface IIntentReceiver { - void performReceive(in Intent intent, int resultCode, - String data, in Bundle extras, boolean ordered, boolean sticky); + void performReceive(in Intent intent, int resultCode, String data, + in Bundle extras, boolean ordered, boolean sticky, int sendingUser); } diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java index 079241a..6c3cf99 100644 --- a/core/java/android/content/IntentSender.java +++ b/core/java/android/content/IntentSender.java @@ -114,8 +114,8 @@ public class IntentSender implements Parcelable { mWho = who; mHandler = handler; } - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean serialized, boolean sticky) { + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean serialized, boolean sticky, int sendingUser) { mIntent = intent; mResultCode = resultCode; mResultData = data; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 3035729..0b320f0 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -372,6 +372,12 @@ public class ActivityInfo extends ComponentInfo public static final int CONFIG_DENSITY = 0x1000; /** * Bit in {@link #configChanges} that indicates that the activity + * can itself handle the change to layout direction. Set from the + * {@link android.R.attr#configChanges} attribute. + */ + public static final int CONFIG_LAYOUT_DIRECTION = 0x2000; + /** + * Bit in {@link #configChanges} that indicates that the activity * can itself handle changes to the font scaling factor. Set from the * {@link android.R.attr#configChanges} attribute. This is * not a core resource configutation, but a higher-level value, so its @@ -398,6 +404,7 @@ public class ActivityInfo extends ComponentInfo 0x0200, // SCREEN SIZE 0x2000, // SMALLEST SCREEN SIZE 0x0100, // DENSITY + 0x4000, // LAYOUT DIRECTION }; /** @hide * Convert Java change bits to native. @@ -434,8 +441,9 @@ public class ActivityInfo extends ComponentInfo * {@link #CONFIG_MCC}, {@link #CONFIG_MNC}, * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN}, * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION}, - * {@link #CONFIG_ORIENTATION}, and {@link #CONFIG_SCREEN_LAYOUT}. Set from the - * {@link android.R.attr#configChanges} attribute. + * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT} and + * {@link #CONFIG_LAYOUT_DIRECTION}. Set from the {@link android.R.attr#configChanges} + * attribute. */ public int configChanges; diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 52b6498..0b77842 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -125,7 +125,25 @@ public final class Configuration implements Parcelable, Comparable<Configuration * <a href="{@docRoot}guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a> * resource qualifier. */ public static final int SCREENLAYOUT_LONG_YES = 0x20; - + + /** Constant for {@link #screenLayout}: bits that encode the layout direction. */ + public static final int SCREENLAYOUT_LAYOUTDIR_MASK = 0xC0; + /** Constant for {@link #screenLayout}: bits shift to get the layout direction. */ + public static final int SCREENLAYOUT_LAYOUTDIR_SHIFT = 6; + /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} + * value indicating that no layout dir has been set. */ + public static final int SCREENLAYOUT_LAYOUTDIR_UNDEFINED = 0x00; + /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} + * value indicating that a layout dir has been set to LTR. */ + public static final int SCREENLAYOUT_LAYOUTDIR_LTR = 0x01 << SCREENLAYOUT_LAYOUTDIR_SHIFT; + /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_LAYOUTDIR_MASK} + * value indicating that a layout dir has been set to RTL. */ + public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT; + + /** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */ + public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED | + SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED; + /** * Special flag we generate to indicate that the screen layout requires * us to use a compatibility mode for apps that are not modern layout @@ -146,6 +164,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration * is wider/taller than normal. They may be one of * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}. * + * <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout + * is either LTR or RTL. They may be one of + * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}. + * * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting * Multiple Screens</a> for more information. */ @@ -442,11 +464,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration public int compatSmallestScreenWidthDp; /** - * @hide The layout direction associated to the current Locale - */ - public int layoutDirection; - - /** * @hide Internal book-keeping. */ public int seq; @@ -472,7 +489,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration mnc = o.mnc; if (o.locale != null) { locale = (Locale) o.locale.clone(); - layoutDirection = o.layoutDirection; } userSetLocale = o.userSetLocale; touchscreen = o.touchscreen; @@ -517,10 +533,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration } else { sb.append(" ?locale"); } - switch (layoutDirection) { - case View.LAYOUT_DIRECTION_LTR: /* ltr not interesting */ break; - case View.LAYOUT_DIRECTION_RTL: sb.append(" rtl"); break; - default: sb.append(" layoutDir="); sb.append(layoutDirection); break; + int layoutDir = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK); + switch (layoutDir) { + case SCREENLAYOUT_LAYOUTDIR_UNDEFINED: sb.append(" ?layoutDir"); break; + case SCREENLAYOUT_LAYOUTDIR_LTR: sb.append(" ltr"); break; + case SCREENLAYOUT_LAYOUTDIR_RTL: sb.append(" rtl"); break; + default: sb.append(" layoutDir="); + sb.append(layoutDir >> SCREENLAYOUT_LAYOUTDIR_SHIFT); break; } if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp"); @@ -643,13 +662,12 @@ public final class Configuration implements Parcelable, Comparable<Configuration navigation = NAVIGATION_UNDEFINED; navigationHidden = NAVIGATIONHIDDEN_UNDEFINED; orientation = ORIENTATION_UNDEFINED; - screenLayout = SCREENLAYOUT_SIZE_UNDEFINED; + screenLayout = SCREENLAYOUT_UNDEFINED; uiMode = UI_MODE_TYPE_UNDEFINED; screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED; screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED; smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; densityDpi = DENSITY_DPI_UNDEFINED; - layoutDirection = View.LAYOUT_DIRECTION_LTR; seq = 0; } @@ -685,7 +703,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_LOCALE; locale = delta.locale != null ? (Locale) delta.locale.clone() : null; - layoutDirection = LocaleUtil.getLayoutDirectionFromLocale(locale); + // If locale has changed, then layout direction is also changed ... + changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; + // ... and we need to update the layout direction (represented by the first + // 2 most significant bits in screenLayout). + setLayoutDirection(locale); } if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0))) { @@ -727,10 +749,17 @@ public final class Configuration implements Parcelable, Comparable<Configuration changed |= ActivityInfo.CONFIG_ORIENTATION; orientation = delta.orientation; } - if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED - && screenLayout != delta.screenLayout) { + if (getScreenLayoutNoDirection(delta.screenLayout) != + (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED) + && (getScreenLayoutNoDirection(screenLayout) != + getScreenLayoutNoDirection(delta.screenLayout))) { changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; - screenLayout = delta.screenLayout; + // We need to preserve the previous layout dir bits if they were defined + if ((delta.screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) == 0) { + screenLayout = (screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK)|delta.screenLayout; + } else { + screenLayout = delta.screenLayout; + } } if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) && uiMode != delta.uiMode) { @@ -771,7 +800,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp; } - if (delta.seq != 0) { seq = delta.seq; } @@ -807,6 +835,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}. + * {@link android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION + * PackageManager.ActivityInfo.CONFIG_LAYOUT_DIRECTION}. */ public int diff(Configuration delta) { int changed = 0; @@ -822,6 +852,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (delta.locale != null && (locale == null || !locale.equals(delta.locale))) { changed |= ActivityInfo.CONFIG_LOCALE; + changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION; } if (delta.touchscreen != TOUCHSCREEN_UNDEFINED && touchscreen != delta.touchscreen) { @@ -851,8 +882,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration && orientation != delta.orientation) { changed |= ActivityInfo.CONFIG_ORIENTATION; } - if (delta.screenLayout != SCREENLAYOUT_SIZE_UNDEFINED - && screenLayout != delta.screenLayout) { + if (getScreenLayoutNoDirection(delta.screenLayout) != + (SCREENLAYOUT_SIZE_UNDEFINED | SCREENLAYOUT_LONG_UNDEFINED) + && getScreenLayoutNoDirection(screenLayout) != + getScreenLayoutNoDirection(delta.screenLayout)) { changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT; } if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED) @@ -875,7 +908,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration && densityDpi != delta.densityDpi) { changed |= ActivityInfo.CONFIG_DENSITY; } - + return changed; } @@ -963,7 +996,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(compatScreenWidthDp); dest.writeInt(compatScreenHeightDp); dest.writeInt(compatSmallestScreenWidthDp); - dest.writeInt(layoutDirection); dest.writeInt(seq); } @@ -992,7 +1024,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration compatScreenWidthDp = source.readInt(); compatScreenHeightDp = source.readInt(); compatSmallestScreenWidthDp = source.readInt(); - layoutDirection = source.readInt(); seq = source.readInt(); } @@ -1100,4 +1131,50 @@ public final class Configuration implements Parcelable, Comparable<Configuration result = 31 * result + densityDpi; return result; } + + /** + * Set the locale. This is the preferred way for setting up the locale (instead of using the + * direct accessor). This will also set the userLocale and layout direction according to + * the locale. + * + * @param loc The locale. Can be null. + */ + public void setLocale(Locale loc) { + locale = loc; + userSetLocale = true; + setLayoutDirection(locale); + } + + /** + * Return the layout direction. Will be either {@link View#LAYOUT_DIRECTION_LTR} or + * {@link View#LAYOUT_DIRECTION_RTL}. + * + * @return the layout direction + */ + public int getLayoutDirection() { + // We need to substract one here as the configuration values are using "0" as undefined thus + // having LRT set to "1" and RTL set to "2" + return ((screenLayout&SCREENLAYOUT_LAYOUTDIR_MASK) >> SCREENLAYOUT_LAYOUTDIR_SHIFT) - 1; + } + + /** + * Set the layout direction from the Locale. + * + * @param locale The Locale. If null will set the layout direction to + * {@link View#LAYOUT_DIRECTION_LTR}. If not null will set it to the layout direction + * corresponding to the Locale. + * + * @see {@link View#LAYOUT_DIRECTION_LTR} and {@link View#LAYOUT_DIRECTION_RTL} + */ + public void setLayoutDirection(Locale locale) { + // There is a "1" difference between the configuration values for + // layout direction and View constants for layout direction, just add "1". + final int layoutDirection = 1 + LocaleUtil.getLayoutDirectionFromLocale(locale); + screenLayout = (screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK)| + (layoutDirection << SCREENLAYOUT_LAYOUTDIR_SHIFT); + } + + private static int getScreenLayoutNoDirection(int screenLayout) { + return screenLayout&~SCREENLAYOUT_LAYOUTDIR_MASK; + } } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 7559f1e..42a6bdc 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1444,12 +1444,14 @@ public class Resources { } if (mTmpConfig.locale == null) { mTmpConfig.locale = Locale.getDefault(); + mTmpConfig.setLayoutDirection(mTmpConfig.locale); } configChanges = mConfiguration.updateFrom(mTmpConfig); configChanges = ActivityInfo.activityInfoConfigToNative(configChanges); } if (mConfiguration.locale == null) { mConfiguration.locale = Locale.getDefault(); + mConfiguration.setLayoutDirection(mConfiguration.locale); } if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) { mMetrics.densityDpi = mConfiguration.densityDpi; diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index a30567f..9b62a51 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -1517,6 +1517,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { // because the voice search activity will always need to insert "QUERY" into // it anyway. Bundle queryExtras = new Bundle(); + if (mAppSearchData != null) { + queryExtras.putParcelable(SearchManager.APP_DATA, mAppSearchData); + } // Now build the intent to launch the voice search. Add all necessary // extras to launch the voice recognizer, and then all the necessary extras diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index e8bf9d9..485bd37 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -379,7 +379,7 @@ public class Toast { // We can resolve the Gravity here by using the Locale for getting // the layout direction final Configuration config = mView.getContext().getResources().getConfiguration(); - final int gravity = Gravity.getAbsoluteGravity(mGravity, config.layoutDirection); + final int gravity = Gravity.getAbsoluteGravity(mGravity, config.getLayoutDirection()); mParams.gravity = gravity; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) { mParams.horizontalWeight = 1.0f; diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java index 7d1231e..f173327 100644 --- a/core/java/com/android/internal/app/LocalePicker.java +++ b/core/java/com/android/internal/app/LocalePicker.java @@ -243,10 +243,9 @@ public class LocalePicker extends ListFragment { IActivityManager am = ActivityManagerNative.getDefault(); Configuration config = am.getConfiguration(); - config.locale = locale; - - // indicate this isn't some passing default - the user wants this remembered - config.userSetLocale = true; + // Will set userSetLocale to indicate this isn't some passing default - the user + // wants this remembered + config.setLocale(locale); am.updateConfiguration(config); // Trigger the dirty bit for the Settings Provider. diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml index df999f0..c6ddd1b 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_status_land.xml @@ -109,7 +109,7 @@ /> <TextView - android:id="@+id/propertyOf" + android:id="@+id/owner_info" android:lineSpacingExtra="8dip" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml index 565785b..765dc95 100644 --- a/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml +++ b/core/res/res/layout-sw600dp/keyguard_screen_status_port.xml @@ -109,7 +109,7 @@ /> <TextView - android:id="@+id/propertyOf" + android:id="@+id/owner_info" android:lineSpacingExtra="8dip" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/core/res/res/layout/keyguard_navigation.xml b/core/res/res/layout/keyguard_navigation.xml index f9e3ef8..a033101 100644 --- a/core/res/res/layout/keyguard_navigation.xml +++ b/core/res/res/layout/keyguard_navigation.xml @@ -31,11 +31,11 @@ android:padding="10dip" android:clickable="true"> - <TextView - android:layout_width="20dip" - android:layout_height="wrap_content" - android:textSize="28dp" - android:text="@string/kg_temp_back_string" /> + <ImageView + android:src="?android:attr/homeAsUpIndicator" + android:layout_gravity="center_vertical|start" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> <!-- message area for security screen --> <TextView @@ -43,6 +43,7 @@ android:layout_width="0dip" android:layout_height="wrap_content" android:layout_weight="1" + android:layout_gravity="end" android:singleLine="true" android:ellipsize="marquee" android:layout_marginEnd="6dip" diff --git a/core/res/res/layout/keyguard_status_view.xml b/core/res/res/layout/keyguard_status_view.xml index f8d05b7..37e6779 100644 --- a/core/res/res/layout/keyguard_status_view.xml +++ b/core/res/res/layout/keyguard_status_view.xml @@ -94,7 +94,7 @@ </LinearLayout> <TextView - android:id="@*android:id/status1" + android:id="@+id/status1" android:layout_gravity="end" android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin" android:singleLine="true" @@ -105,7 +105,18 @@ /> <TextView - android:id="@*android:id/carrier" + android:id="@+id/owner_info" + android:layout_gravity="end" + android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin" + android:singleLine="true" + android:ellipsize="marquee" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textSize="@*android:dimen/keyguard_lockscreen_status_line_font_size" + android:drawablePadding="4dip" + /> + + <TextView + android:id="@+id/carrier" android:layout_gravity="end" android:layout_marginEnd="@*android:dimen/keyguard_lockscreen_status_line_font_right_margin" android:singleLine="true" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 1c3318d..3a69937 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -639,6 +639,8 @@ physical screen size has changed such as switching to an external display. --> <flag name="smallestScreenSize" value="0x0800" /> + <!-- The layout direction has changed. For example going from LTR to RTL. --> + <flag name="layoutDirection" value="0x2000" /> <!-- The font scaling factor has changed, that is the user has selected a new global font size. --> <flag name="fontScale" value="0x40000000" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 8e0eb15..c993c0b 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -710,6 +710,7 @@ <java-symbol type="string" name="policydesc_setGlobalProxy" /> <java-symbol type="string" name="policydesc_watchLogin" /> <java-symbol type="string" name="policydesc_wipeData" /> + <java-symbol type="string" name="policydesc_disableKeyguardWidgets" /> <java-symbol type="string" name="policylab_disableCamera" /> <java-symbol type="string" name="policylab_encryptedStorage" /> <java-symbol type="string" name="policylab_expirePassword" /> @@ -719,6 +720,7 @@ <java-symbol type="string" name="policylab_setGlobalProxy" /> <java-symbol type="string" name="policylab_watchLogin" /> <java-symbol type="string" name="policylab_wipeData" /> + <java-symbol type="string" name="policylab_disableKeyguardWidgets" /> <java-symbol type="string" name="postalTypeCustom" /> <java-symbol type="string" name="postalTypeHome" /> <java-symbol type="string" name="postalTypeOther" /> @@ -1293,7 +1295,7 @@ <java-symbol type="id" name="passwordEntry" /> <java-symbol type="id" name="pinDel" /> <java-symbol type="id" name="pinDisplay" /> - <java-symbol type="id" name="propertyOf" /> + <java-symbol type="id" name="owner_info" /> <java-symbol type="id" name="pukDel" /> <java-symbol type="id" name="pukDisplay" /> <java-symbol type="id" name="right_icon" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 381055f..d2951bf 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1693,6 +1693,10 @@ <string name="policylab_disableCamera">Disable cameras</string> <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]--> <string name="policydesc_disableCamera">Prevent use of all device cameras.</string> + <!-- Title of policy access to disable all device cameras [CHAR LIMIT=30]--> + <string name="policylab_disableKeyguardWidgets">Disable widgets on keyguard</string> + <!-- Description of policy access to disable all device cameras [CHAR LIMIT=110]--> + <string name="policydesc_disableKeyguardWidgets">Prevent use of some or all widgets on keyguard.</string> <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. --> diff --git a/docs/html/training/basics/activity-lifecycle/recreating.jd b/docs/html/training/basics/activity-lifecycle/recreating.jd index 3bbf0bb..8c7126a 100644 --- a/docs/html/training/basics/activity-lifecycle/recreating.jd +++ b/docs/html/training/basics/activity-lifecycle/recreating.jd @@ -51,7 +51,7 @@ the user rotates the screen. When the screen changes orientation, the system des the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).</p> -<p>By default, the system uses the {@link android.os.Bundle} instance state to saves information +<p>By default, the system uses the {@link android.os.Bundle} instance state to save information about each {@link android.view.View} object in your activity layout (such as the text value entered into an {@link android.widget.EditText} object). So, if your activity instance is destroyed and recreated, the state of the layout is automatically restored to its previous state. However, your diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h index 23bca3e..48f5bf3 100644 --- a/include/androidfw/ResourceTypes.h +++ b/include/androidfw/ResourceTypes.h @@ -957,6 +957,13 @@ struct ResTable_config SCREENLONG_ANY = ACONFIGURATION_SCREENLONG_ANY << SHIFT_SCREENLONG, SCREENLONG_NO = ACONFIGURATION_SCREENLONG_NO << SHIFT_SCREENLONG, SCREENLONG_YES = ACONFIGURATION_SCREENLONG_YES << SHIFT_SCREENLONG, + + // screenLayout bits for layout direction. + MASK_LAYOUTDIR = 0xC0, + SHIFT_LAYOUTDIR = 6, + LAYOUTDIR_ANY = ACONFIGURATION_LAYOUTDIR_ANY << SHIFT_LAYOUTDIR, + LAYOUTDIR_LTR = ACONFIGURATION_LAYOUTDIR_LTR << SHIFT_LAYOUTDIR, + LAYOUTDIR_RTL = ACONFIGURATION_LAYOUTDIR_RTL << SHIFT_LAYOUTDIR, }; enum { @@ -1020,7 +1027,8 @@ struct ResTable_config CONFIG_SMALLEST_SCREEN_SIZE = ACONFIGURATION_SMALLEST_SCREEN_SIZE, CONFIG_VERSION = ACONFIGURATION_VERSION, CONFIG_SCREEN_LAYOUT = ACONFIGURATION_SCREEN_LAYOUT, - CONFIG_UI_MODE = ACONFIGURATION_UI_MODE + CONFIG_UI_MODE = ACONFIGURATION_UI_MODE, + CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR, }; // Compare two configuration, returning CONFIG_* flags set for each value @@ -1061,7 +1069,7 @@ struct ResTable_config * There should be one of these chunks for each resource type. * * This structure is followed by an array of integers providing the set of - * configuation change flags (ResTable_config::CONFIG_*) that have multiple + * configuration change flags (ResTable_config::CONFIG_*) that have multiple * resources for that configuration. In addition, the high bit is set if that * resource has been made public. */ diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 8cce191..069dfa3 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1470,6 +1470,9 @@ int ResTable_config::compareLogical(const ResTable_config& o) const { if (country[1] != o.country[1]) { return country[1] < o.country[1] ? -1 : 1; } + if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) { + return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1; + } if (smallestScreenWidthDp != o.smallestScreenWidthDp) { return smallestScreenWidthDp < o.smallestScreenWidthDp ? -1 : 1; } @@ -1558,6 +1561,13 @@ bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const { } } + if (screenLayout || o.screenLayout) { + if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0) { + if (!(screenLayout & MASK_LAYOUTDIR)) return false; + if (!(o.screenLayout & MASK_LAYOUTDIR)) return true; + } + } + if (smallestScreenWidthDp || o.smallestScreenWidthDp) { if (smallestScreenWidthDp != o.smallestScreenWidthDp) { if (!smallestScreenWidthDp) return false; @@ -1683,6 +1693,15 @@ bool ResTable_config::isBetterThan(const ResTable_config& o, } } + if (screenLayout || o.screenLayout) { + if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0 + && (requested->screenLayout & MASK_LAYOUTDIR)) { + int myLayoutDir = screenLayout & MASK_LAYOUTDIR; + int oLayoutDir = o.screenLayout & MASK_LAYOUTDIR; + return (myLayoutDir > oLayoutDir); + } + } + if (smallestScreenWidthDp || o.smallestScreenWidthDp) { // The configuration closest to the actual size is best. // We assume that larger configs have already been filtered @@ -1906,6 +1925,12 @@ bool ResTable_config::match(const ResTable_config& settings) const { } } if (screenConfig != 0) { + const int layoutDir = screenLayout&MASK_LAYOUTDIR; + const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR; + if (layoutDir != 0 && layoutDir != setLayoutDir) { + return false; + } + const int screenSize = screenLayout&MASK_SCREENSIZE; const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE; // Any screen sizes for larger screens than the setting do not @@ -2032,6 +2057,21 @@ String8 ResTable_config::toString() const { if (res.size() > 0) res.append("-"); res.append(country, 2); } + if ((screenLayout&MASK_LAYOUTDIR) != 0) { + if (res.size() > 0) res.append("-"); + switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) { + case ResTable_config::LAYOUTDIR_LTR: + res.append("ltr"); + break; + case ResTable_config::LAYOUTDIR_RTL: + res.append("rtl"); + break; + default: + res.appendFormat("layoutDir=%d", + dtohs(screenLayout&ResTable_config::MASK_LAYOUTDIR)); + break; + } + } if (smallestScreenWidthDp != 0) { if (res.size() > 0) res.append("-"); res.appendFormat("sw%ddp", dtohs(smallestScreenWidthDp)); diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp index 7eb51dd..74cf80e 100644 --- a/native/android/configuration.cpp +++ b/native/android/configuration.cpp @@ -123,6 +123,11 @@ int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) { return config->smallestScreenWidthDp; } +int32_t AConfiguration_getLayoutDirection(AConfiguration* config) { + return (config->screenLayout&ResTable_config::MASK_LAYOUTDIR) + >> ResTable_config::SHIFT_LAYOUTDIR; +} + // ---------------------------------------------------------------------- void AConfiguration_setMcc(AConfiguration* config, int32_t mcc) { @@ -210,6 +215,11 @@ void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t val config->smallestScreenWidthDp = value; } +void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) { + config->screenLayout = (config->screenLayout&~ResTable_config::MASK_LAYOUTDIR) + | ((value<<ResTable_config::SHIFT_LAYOUTDIR)&ResTable_config::MASK_LAYOUTDIR); +} + // ---------------------------------------------------------------------- int32_t AConfiguration_diff(AConfiguration* config1, AConfiguration* config2) { diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index b185471..7176f32 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -167,7 +167,7 @@ android:name=".BeanBag" android:exported="true" android:label="BeanBag" - android:icon="@drawable/redbeandroid" + android:icon="@drawable/redbean2" android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen" android:hardwareAccelerated="true" android:launchMode="singleInstance" @@ -184,7 +184,9 @@ <service android:name=".BeanBagDream" android:exported="true" - android:label="Beans in space"> + android:label="@string/jelly_bean_dream_name" + android:enabled="false" + > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 5747f22..609d63b 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -397,4 +397,7 @@ <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] --> <string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string> + + <!-- Name of the Jelly Bean platlogo screensaver --> + <string name="jelly_bean_dream_name">BeanFlinger</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/BeanBag.java b/packages/SystemUI/src/com/android/systemui/BeanBag.java index 616d72f..f5a90ca 100644 --- a/packages/SystemUI/src/com/android/systemui/BeanBag.java +++ b/packages/SystemUI/src/com/android/systemui/BeanBag.java @@ -24,6 +24,7 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.Bitmap; @@ -40,6 +41,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; import android.os.SystemClock; +import android.provider.Settings; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Pair; @@ -402,6 +404,11 @@ public class BeanBag extends Activity { public void onStart() { super.onStart(); + // ACHIEVEMENT UNLOCKED + PackageManager pm = getPackageManager(); + pm.setComponentEnabledSetting(new ComponentName(this, BeanBagDream.class), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); + getWindow().addFlags( WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 3e96f9b..e761847 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -2841,7 +2841,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); mDecor.setLayoutDirection( - getContext().getResources().getConfiguration().layoutDirection); + getContext().getResources().getConfiguration().getLayoutDirection()); } if (mContentParent == null) { mContentParent = generateLayout(mDecor); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 2551c04..e0ba211 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -172,7 +172,7 @@ public class KeyguardHostView extends KeyguardViewBase { protected void onAttachedToWindow() { super.onAttachedToWindow(); mAppWidgetHost.startListening(); - populateWidgets(); + maybePopulateWidgets(); } @Override @@ -581,7 +581,12 @@ public class KeyguardHostView extends KeyguardViewBase { addWidget(view); } - private void populateWidgets() { + private void maybePopulateWidgets() { + if (mLockPatternUtils.getDevicePolicyManager().getKeyguardWidgetsDisabled(null) + != DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_NONE) { + Log.v(TAG, "Keyguard widgets disabled because of device policy admin"); + return; + } SharedPreferences prefs = mContext.getSharedPreferences( KEYGUARD_WIDGET_PREFS, Context.MODE_PRIVATE); for (String key : prefs.getAll().keySet()) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java index 6938561..b2ce73e 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPasswordView.java @@ -256,12 +256,10 @@ public class KeyguardPasswordView extends LinearLayout private void verifyPasswordAndUnlock() { String entry = mPasswordEntry.getText().toString(); - boolean wrongPassword = true; if (mLockPatternUtils.checkPassword(entry)) { mCallback.reportSuccessfulUnlockAttempt(); KeyStore.getInstance().password(entry); mCallback.dismiss(true); - wrongPassword = false; } else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) { // to avoid accidental lockout, only count attempts that are long enough to be a // real password. This may require some tweaking. @@ -271,9 +269,9 @@ public class KeyguardPasswordView extends LinearLayout long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); handleAttemptLockout(deadline); } + mNavigationManager.setMessage( + mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin); } - mNavigationManager.setMessage(wrongPassword ? - (mIsAlpha ? R.string.kg_wrong_password : R.string.kg_wrong_pin) : 0); mPasswordEntry.setText(""); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java index 294ea5c..4861b78 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java @@ -91,8 +91,6 @@ public class KeyguardSimPinView extends LinearLayout } }); } - - setFocusableInTouchMode(true); reset(); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java index 06ed88a..20fad0b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStatusViewManager.java @@ -119,7 +119,7 @@ class KeyguardStatusViewManager { mDateView = (TextView) findViewById(R.id.date); mStatus1View = (TextView) findViewById(R.id.status1); mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); - mOwnerInfoView = (TextView) findViewById(R.id.propertyOf); + mOwnerInfoView = (TextView) findViewById(R.id.owner_info); mDigitalClock = (DigitalClock) findViewById(R.id.time); // Registering this callback immediately updates the battery state, among other things. diff --git a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java index 409f87b..b6ffde0 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard_obsolete/KeyguardStatusViewManager.java @@ -179,7 +179,7 @@ class KeyguardStatusViewManager implements OnClickListener { mDateView = (TextView) findViewById(R.id.date); mStatus1View = (TextView) findViewById(R.id.status1); mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); - mOwnerInfoView = (TextView) findViewById(R.id.propertyOf); + mOwnerInfoView = (TextView) findViewById(R.id.owner_info); mTransportView = (TransportControlView) findViewById(R.id.transport); mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton); mEmergencyCallButtonEnabledInScreen = emergencyButtonEnabledInScreen; diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index b869abd..63761cc 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -27,7 +27,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; -import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -151,7 +150,7 @@ class AppWidgetService extends IAppWidgetService.Stub // Register for the boot completed broadcast, so we can send the // ENABLE broacasts. If we try to send them now, they time out, // because the system isn't ready to handle them yet. - mContext.registerReceiver(mBroadcastReceiver, + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); // Register for configuration changes so we can update the names @@ -166,12 +165,14 @@ class AppWidgetService extends IAppWidgetService.Stub filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); - mContext.registerReceiver(mBroadcastReceiver, filter); + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + filter, null, null); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); - mContext.registerReceiver(mBroadcastReceiver, sdFilter); + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, + sdFilter, null, null); IntentFilter userFilter = new IntentFilter(); userFilter.addAction(Intent.ACTION_USER_REMOVED); @@ -181,6 +182,15 @@ class AppWidgetService extends IAppWidgetService.Stub onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1)); } }, userFilter); + + IntentFilter userStopFilter = new IntentFilter(); + userStopFilter.addAction(Intent.ACTION_USER_STOPPED); + mContext.registerReceiverAsUser(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + onUserStopped(getSendingUserId()); + } + }, UserHandle.ALL, userFilter, null, null); } @Override @@ -254,6 +264,9 @@ class AppWidgetService extends IAppWidgetService.Stub } } + public void onUserStopped(int userId) { + } + private AppWidgetServiceImpl getImplForUser(int userId) { AppWidgetServiceImpl service = mAppWidgetServices.get(userId); if (service == null) { @@ -370,9 +383,17 @@ class AppWidgetService extends IAppWidgetService.Stub service.onConfigurationChanged(); } } else { - for (int i = 0; i < mAppWidgetServices.size(); i++) { - AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); - service.onBroadcastReceived(intent); + int sendingUser = getSendingUserId(); + if (sendingUser == UserHandle.USER_ALL) { + for (int i = 0; i < mAppWidgetServices.size(); i++) { + AppWidgetServiceImpl service = mAppWidgetServices.valueAt(i); + service.onBroadcastReceived(intent); + } + } else { + AppWidgetServiceImpl service = mAppWidgetServices.get(sendingUser); + if (service != null) { + service.onBroadcastReceived(intent); + } } } } diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 77b062c..61517b1 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -177,6 +177,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { static final long DEF_PASSWORD_EXPIRATION_DATE = 0; long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE; + static final int DEF_KEYGUARD_WIDGET_DISABLED = 0; // none + int disableKeyguardWidgets = DEF_KEYGUARD_WIDGET_DISABLED; + boolean encryptionRequested = false; boolean disableCamera = false; @@ -286,6 +289,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.attribute(null, "value", Boolean.toString(disableCamera)); out.endTag(null, "disable-camera"); } + if (disableKeyguardWidgets != DEF_KEYGUARD_WIDGET_DISABLED) { + out.startTag(null, "disable-keyguard-widgets"); + out.attribute(null, "value", Integer.toString(disableKeyguardWidgets)); + out.endTag(null, "disable-keyguard-widgets"); + } } void readFromXml(XmlPullParser parser) @@ -2093,6 +2101,46 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + /** + * Selectively disable keyguard widgets. + */ + public void setKeyguardWidgetsDisabled(ComponentName who, int which) { + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + ActiveAdmin ap = getActiveAdminForCallerLocked(who, + DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_WIDGETS); + if ((ap.disableKeyguardWidgets & which) != which) { + ap.disableKeyguardWidgets |= which; + saveSettingsLocked(); + } + syncDeviceCapabilitiesLocked(); + } + } + + /** + * Gets the disabled state for widgets in keyguard for the given admin, + * or the aggregate of all active admins if who is null. + */ + public int getKeyguardWidgetsDisabled(ComponentName who) { + synchronized (this) { + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return (admin != null) ? admin.disableKeyguardWidgets : 0; + } + + // Determine whether or not keyguard widgets are disabled for any active admins. + final int N = mAdminList.size(); + int which = 0; + for (int i = 0; i < N; i++) { + ActiveAdmin admin = mAdminList.get(i); + which |= admin.disableKeyguardWidgets; + } + return which; + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 590e9d9..e670da0 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -116,6 +116,7 @@ import android.os.UserManager; import android.provider.Settings; import android.text.format.Time; import android.util.EventLog; +import android.util.LocaleUtil; import android.util.Log; import android.util.Pair; import android.util.PrintWriterPrinter; @@ -153,7 +154,6 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -495,7 +495,8 @@ public final class ActivityManagerService extends ActivityManagerNative @Override protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) { - if (userId == UserHandle.USER_ALL || userId == filter.owningUserId) { + if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL + || userId == filter.owningUserId) { return super.newResult(filter, match, userId); } return null; @@ -1530,7 +1531,8 @@ public final class ActivityManagerService extends ActivityManagerNative ConfigurationInfo.GL_ES_VERSION_UNDEFINED); mConfiguration.setToDefaults(); - mConfiguration.locale = Locale.getDefault(); + mConfiguration.setLocale(Locale.getDefault()); + mConfigurationSeq = mConfiguration.seq = 1; mProcessStats.init(); @@ -3570,15 +3572,32 @@ public final class ActivityManagerService extends ActivityManagerNative public void closeSystemDialogs(String reason) { enforceNotIsolatedCaller("closeSystemDialogs"); + final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); - synchronized (this) { - closeSystemDialogsLocked(uid, reason); + try { + synchronized (this) { + // Only allow this from foreground processes, so that background + // applications can't abuse it to prevent system UI from being shown. + if (uid >= Process.FIRST_APPLICATION_UID) { + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + if (proc.curRawAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { + Slog.w(TAG, "Ignoring closeSystemDialogs " + reason + + " from background process " + proc); + return; + } + } + closeSystemDialogsLocked(reason); + } + } finally { + Binder.restoreCallingIdentity(origId); } - Binder.restoreCallingIdentity(origId); } - void closeSystemDialogsLocked(int callingUid, String reason) { + void closeSystemDialogsLocked(String reason) { Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); if (reason != null) { @@ -3594,14 +3613,9 @@ public final class ActivityManagerService extends ActivityManagerNative } } - final long origId = Binder.clearCallingIdentity(); - try { - broadcastIntentLocked(null, null, intent, null, - null, 0, null, null, null, false, false, -1, - callingUid, UserHandle.USER_ALL); - } finally { - Binder.restoreCallingIdentity(origId); - } + broadcastIntentLocked(null, null, intent, null, + null, 0, null, null, null, false, false, -1, + Process.SYSTEM_UID, UserHandle.USER_ALL); } public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) @@ -7549,7 +7563,7 @@ public final class ActivityManagerService extends ActivityManagerNative finisher = new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, - boolean sticky) { + boolean sticky, int sendingUser) { // The raw IIntentReceiver interface is called // with the AM lock held, so redispatch to // execute our code without the lock. @@ -11038,9 +11052,10 @@ public final class ActivityManagerService extends ActivityManagerNative } public Intent registerReceiver(IApplicationThread caller, String callerPackage, - IIntentReceiver receiver, IntentFilter filter, String permission) { + IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { enforceNotIsolatedCaller("registerReceiver"); int callingUid; + int callingPid; synchronized(this) { ProcessRecord callerApp = null; if (caller != null) { @@ -11057,11 +11072,16 @@ public final class ActivityManagerService extends ActivityManagerNative + " is not running in process " + callerApp); } callingUid = callerApp.info.uid; + callingPid = callerApp.pid; } else { callerPackage = null; callingUid = Binder.getCallingUid(); + callingPid = Binder.getCallingPid(); } + userId = this.handleIncomingUserLocked(callingPid, callingUid, userId, + true, true, "registerReceiver", callerPackage); + List allSticky = null; // Look for any matching sticky broadcasts... @@ -11095,9 +11115,8 @@ public final class ActivityManagerService extends ActivityManagerNative ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { - rl = new ReceiverList(this, callerApp, - Binder.getCallingPid(), - Binder.getCallingUid(), receiver); + rl = new ReceiverList(this, callerApp, callingPid, callingUid, + userId, receiver); if (rl.app != null) { rl.app.receivers.add(rl); } else { @@ -11109,9 +11128,21 @@ public final class ActivityManagerService extends ActivityManagerNative rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); + } else if (rl.uid != callingUid) { + throw new IllegalArgumentException( + "Receiver requested to register for uid " + callingUid + + " was previously registered for uid " + rl.uid); + } else if (rl.pid != callingPid) { + throw new IllegalArgumentException( + "Receiver requested to register for pid " + callingPid + + " was previously registered for pid " + rl.pid); + } else if (rl.userId != userId) { + throw new IllegalArgumentException( + "Receiver requested to register for user " + userId + + " was previously registered for user " + rl.userId); } BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, - permission, callingUid); + permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadast"); @@ -13834,7 +13865,7 @@ public final class ActivityManagerService extends ActivityManagerNative final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() { @Override public void performReceive(Intent intent, int resultCode, String data, - Bundle extras, boolean ordered, boolean sticky) { + Bundle extras, boolean ordered, boolean sticky, int sendingUser) { finishUserStop(uss); } }; diff --git a/services/java/com/android/server/am/BroadcastFilter.java b/services/java/com/android/server/am/BroadcastFilter.java index b0ccd8f..07440b5 100644 --- a/services/java/com/android/server/am/BroadcastFilter.java +++ b/services/java/com/android/server/am/BroadcastFilter.java @@ -17,7 +17,6 @@ package com.android.server.am; import android.content.IntentFilter; -import android.os.UserHandle; import android.util.PrintWriterPrinter; import android.util.Printer; @@ -32,13 +31,13 @@ class BroadcastFilter extends IntentFilter { final int owningUserId; BroadcastFilter(IntentFilter _filter, ReceiverList _receiverList, - String _packageName, String _requiredPermission, int _owningUid) { + String _packageName, String _requiredPermission, int _owningUid, int _userId) { super(_filter); receiverList = _receiverList; packageName = _packageName; requiredPermission = _requiredPermission; owningUid = _owningUid; - owningUserId = UserHandle.getUserId(owningUid); + owningUserId = _userId; } public void dump(PrintWriter pw, String prefix) { diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index 34dec3a..1b6ff7a 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -222,7 +222,7 @@ public class BroadcastQueue { mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver, mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo), - r.resultCode, r.resultData, r.resultExtras, r.ordered); + r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId); if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + " DELIVERED for app " + app); started = true; @@ -357,15 +357,16 @@ public class BroadcastQueue { private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, - boolean ordered, boolean sticky) throws RemoteException { + boolean ordered, boolean sticky, int sendingUser) throws RemoteException { // Send the intent to the receiver asynchronously using one-way binder calls. if (app != null && app.thread != null) { // If we have an app thread, do the call through that so it is // correctly ordered with other one-way calls. app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, - data, extras, ordered, sticky); + data, extras, ordered, sticky, sendingUser); } else { - receiver.performReceive(intent, resultCode, data, extras, ordered, sticky); + receiver.performReceive(intent, resultCode, data, extras, ordered, + sticky, sendingUser); } } @@ -428,8 +429,8 @@ public class BroadcastQueue { + " (seq=" + seq + "): " + r); } performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, - new Intent(r.intent), r.resultCode, - r.resultData, r.resultExtras, r.ordered, r.initialSticky); + new Intent(r.intent), r.resultCode, r.resultData, + r.resultExtras, r.ordered, r.initialSticky, r.userId); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } @@ -579,7 +580,7 @@ public class BroadcastQueue { } performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, - r.resultData, r.resultExtras, false, false); + r.resultData, r.resultExtras, false, false, r.userId); // Set this to null so that the reference // (local and remote) isnt kept in the mBroadcastHistory. r.resultTo = null; diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java index 37e9017..0f72409 100644 --- a/services/java/com/android/server/am/PendingIntentRecord.java +++ b/services/java/com/android/server/am/PendingIntentRecord.java @@ -285,7 +285,7 @@ class PendingIntentRecord extends IIntentSender.Stub { if (sendFinish) { try { finishedReceiver.performReceive(new Intent(finalIntent), 0, - null, null, false, false); + null, null, false, false, key.userId); } catch (RemoteException e) { } } diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java index 32c24c6..9b6701e 100644 --- a/services/java/com/android/server/am/ReceiverList.java +++ b/services/java/com/android/server/am/ReceiverList.java @@ -39,18 +39,20 @@ class ReceiverList extends ArrayList<BroadcastFilter> public final ProcessRecord app; public final int pid; public final int uid; + public final int userId; BroadcastRecord curBroadcast = null; boolean linkedToDeath = false; String stringName; ReceiverList(ActivityManagerService _owner, ProcessRecord _app, - int _pid, int _uid, IIntentReceiver _receiver) { + int _pid, int _uid, int _userId, IIntentReceiver _receiver) { owner = _owner; receiver = _receiver; app = _app; pid = _pid; uid = _uid; + userId = _userId; } // Want object identity, not the array identity we are inheriting. @@ -67,8 +69,9 @@ class ReceiverList extends ArrayList<BroadcastFilter> } void dumpLocal(PrintWriter pw, String prefix) { - pw.print(prefix); pw.print("app="); pw.print(app); - pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.println(uid); + pw.print(prefix); pw.print("app="); pw.print(app.toShortString()); + pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid); + pw.print(" user="); pw.println(userId); if (curBroadcast != null || linkedToDeath) { pw.print(prefix); pw.print("curBroadcast="); pw.print(curBroadcast); pw.print(" linkedToDeath="); pw.println(linkedToDeath); @@ -103,6 +106,8 @@ class ReceiverList extends ArrayList<BroadcastFilter> sb.append((app != null ? app.processName : "(unknown name)")); sb.append('/'); sb.append(uid); + sb.append("/u"); + sb.append(userId); sb.append((receiver.asBinder() instanceof Binder) ? " local:" : " remote:"); sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder()))); sb.append('}'); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 183f8ec..55da11f 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -208,8 +208,7 @@ public class PackageManagerService extends IPackageManager.Stub { /** * Whether verification is enabled by default. */ - // STOPSHIP: change this to true - private static final boolean DEFAULT_VERIFY_ENABLE = false; + private static final boolean DEFAULT_VERIFY_ENABLE = true; /** * The default maximum time to wait for the verification agent to return in @@ -9635,7 +9634,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkgList.size() > 0) { sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, - Bundle extras, boolean ordered, boolean sticky) throws RemoteException { + Bundle extras, boolean ordered, boolean sticky, + int sendingUser) throws RemoteException { Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, reportStatus ? 1 : 0, 1, keys); mHandler.sendMessage(msg); diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java index c25f010..c6b7e0d 100644 --- a/services/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/java/com/android/server/wm/AppWindowAnimator.java @@ -234,10 +234,8 @@ public class AppWindowAnimator { return false; } - mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges); - } + mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, + "AppWindowToken"); clearAnimation(); animating = false; diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java index afcf339..87a2880 100644 --- a/services/java/com/android/server/wm/DimAnimator.java +++ b/services/java/com/android/server/wm/DimAnimator.java @@ -212,5 +212,12 @@ class DimAnimator { mDimHeight = dimHeight; mDimTarget = dimTarget; } + + Parameters(Parameters o) { + mDimWinAnimator = o.mDimWinAnimator; + mDimWidth = o.mDimWidth; + mDimHeight = o.mDimHeight; + mDimTarget = o.mDimTarget; + } } } diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 1e1b097..f4964cf 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -64,6 +64,7 @@ class DisplayContent { // Accessed directly by all users. boolean layoutNeeded; + int pendingLayoutChanges; DisplayContent(Display display) { mDisplay = display; @@ -84,6 +85,7 @@ class DisplayContent { } DisplayInfo getDisplayInfo() { + mDisplay.getDisplayInfo(mDisplayInfo); return mDisplayInfo; } diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 232f2ed..f0b514c 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -16,12 +16,12 @@ import android.content.Context; import android.os.SystemClock; import android.util.Log; import android.util.Slog; +import android.util.SparseIntArray; import android.view.Display; import android.view.Surface; import android.view.WindowManagerPolicy; import android.view.animation.Animation; -import com.android.internal.policy.impl.PhoneWindowManager; import com.android.server.wm.WindowManagerService.AppWindowAnimParams; import com.android.server.wm.WindowManagerService.LayoutToAnimatorParams; @@ -47,7 +47,8 @@ public class WindowAnimator { int mAdjResult; - int mPendingLayoutChanges; + // Layout changes for individual Displays. Indexed by displayId. + SparseIntArray mPendingLayoutChanges = new SparseIntArray(); /** Overall window dimensions */ int mDw, mDh; @@ -97,7 +98,7 @@ public class WindowAnimator { static class AnimatorToLayoutParams { boolean mUpdateQueued; int mBulkUpdateParams; - int mPendingLayoutChanges; + SparseIntArray mPendingLayoutChanges; WindowState mWindowDetachedWallpaper; } /** Do not modify unless holding mService.mWindowMap or this and mAnimToLayout in that order */ @@ -137,7 +138,7 @@ public class WindowAnimator { final AnimatorToLayoutParams animToLayout = mAnimToLayout; synchronized (animToLayout) { animToLayout.mBulkUpdateParams = mBulkUpdateParams; - animToLayout.mPendingLayoutChanges = mPendingLayoutChanges; + animToLayout.mPendingLayoutChanges = mPendingLayoutChanges.clone(); animToLayout.mWindowDetachedWallpaper = mWindowDetachedWallpaper; if (!animToLayout.mUpdateQueued) { @@ -175,7 +176,7 @@ public class WindowAnimator { // Set the new DimAnimator params. DimAnimator.Parameters dimParams = layoutToAnim.mDimParams; if (dimParams == null) { - mDimParams = dimParams; + mDimParams = null; } else { final WindowStateAnimator newWinAnimator = dimParams.mDimWinAnimator; @@ -186,7 +187,7 @@ public class WindowAnimator { if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null || !existingDimWinAnimator.mSurfaceShown || existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { - mDimParams = dimParams; + mDimParams = new DimAnimator.Parameters(dimParams); } } @@ -214,7 +215,8 @@ public class WindowAnimator { if (!winAnimator.mLastHidden) { winAnimator.hide(); mService.dispatchWallpaperVisibility(wallpaper, false); - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + setPendingLayoutChanges(Display.DEFAULT_DISPLAY, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); } } token.hidden = true; @@ -233,11 +235,8 @@ public class WindowAnimator { mAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("appToken " + appAnimator.mAppToken + " done", - mPendingLayoutChanges); - } + setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, + "appToken " + appAnimator.mAppToken + " done"); if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating " + appAnimator.mAppToken); } @@ -252,11 +251,8 @@ public class WindowAnimator { mAnimating = true; } else if (wasAnimating) { // stopped animating, do one more pass through the layout - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("exiting appToken " + appAnimator.mAppToken - + " done", mPendingLayoutChanges); - } + setAppLayoutChanges(appAnimator, WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, + "exiting appToken " + appAnimator.mAppToken + " done"); if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG, "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken); } @@ -302,10 +298,11 @@ public class WindowAnimator { if (wasAnimating && !winAnimator.mAnimating && mWallpaperTarget == win) { mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + setPendingLayoutChanges(Display.DEFAULT_DISPLAY, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2", - mPendingLayoutChanges); + mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)); } } @@ -315,10 +312,12 @@ public class WindowAnimator { WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Animation started that could impact force hide: " + win); mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED; - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + final int displayId = win.mDisplayContent.getDisplayId(); + setPendingLayoutChanges(displayId, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3", - mPendingLayoutChanges); + mPendingLayoutChanges.get(displayId)); } mService.mFocusMayChange = true; } @@ -377,10 +376,11 @@ public class WindowAnimator { } if (changed && (flags & FLAG_SHOW_WALLPAPER) != 0) { mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE; - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + setPendingLayoutChanges(Display.DEFAULT_DISPLAY, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4", - mPendingLayoutChanges); + mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY)); } } } @@ -390,10 +390,12 @@ public class WindowAnimator { if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) { if (atoken == null || atoken.allDrawn) { if (winAnimator.performShowLocked()) { - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; + final int displayId = win.mDisplayContent.getDisplayId(); + mPendingLayoutChanges.put(displayId, + WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5", - mPendingLayoutChanges); + mPendingLayoutChanges.get(displayId)); } } } @@ -536,14 +538,14 @@ public class WindowAnimator { + wtoken + " numInteresting=" + wtoken.numInterestingWindows + " numDrawn=" + wtoken.numDrawnWindows); // This will set mOrientationChangeComplete and cause a pass through layout. - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + setAppLayoutChanges(appAnimator, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER, + "testTokenMayBeDrawnLocked: freezingScreen"); } else { - mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - mService.debugLayoutRepeats("testTokenMayBeDrawnLocked", - mPendingLayoutChanges); - } - + setAppLayoutChanges(appAnimator, + WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM, + "testTokenMayBeDrawnLocked"); + // We can now show all of the drawn windows! if (!mService.mOpeningApps.contains(wtoken)) { mAnimating |= appAnimator.showAllWindowsLocked(); @@ -557,12 +559,6 @@ public class WindowAnimator { private void performAnimationsLocked(final WinAnimatorList winAnimatorList) { updateWindowsLocked(winAnimatorList); updateWallpaperLocked(winAnimatorList); - - if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { - mPendingActions |= WALLPAPER_ACTION_PENDING; - } - - testTokenMayBeDrawnLocked(); } // TODO(cmautner): Change the following comment when no longer locked on mWindowMap */ @@ -571,13 +567,8 @@ public class WindowAnimator { if (!mInitialized) { return; } - for (int i = mWinAnimatorLists.size() - 1; i >= 0; i--) { - animateLocked(mWinAnimatorLists.get(i)); - } - } - private void animateLocked(final WinAnimatorList winAnimatorList) { - mPendingLayoutChanges = 0; + mPendingLayoutChanges.clear(); mCurrentTime = SystemClock.uptimeMillis(); mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE; boolean wasAnimating = mAnimating; @@ -586,23 +577,29 @@ public class WindowAnimator { Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); } - // Update animations of all applications, including those - // associated with exiting/removed apps + if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( + TAG, ">>> OPEN TRANSACTION animateLocked"); Surface.openTransaction(); - try { updateWindowsAppsAndRotationAnimationsLocked(); - performAnimationsLocked(winAnimatorList); - // THIRD LOOP: Update the surfaces of all windows. + for (int i = mWinAnimatorLists.size() - 1; i >= 0; i--) { + final WinAnimatorList winAnimatorList = mWinAnimatorLists.get(i); - if (mScreenRotationAnimation != null) { - mScreenRotationAnimation.updateSurfacesInTransaction(); + // Update animations of all applications, including those + // associated with exiting/removed apps + performAnimationsLocked(winAnimatorList); + + final int N = winAnimatorList.size(); + for (int j = 0; j < N; j++) { + winAnimatorList.get(j).prepareSurfaceLocked(true); + } } - final int N = winAnimatorList.size(); - for (int i = 0; i < N; i++) { - winAnimatorList.get(i).prepareSurfaceLocked(true); + testTokenMayBeDrawnLocked(); + + if (mScreenRotationAnimation != null) { + mScreenRotationAnimation.updateSurfacesInTransaction(); } if (mDimParams != null) { @@ -629,9 +626,18 @@ public class WindowAnimator { Log.wtf(TAG, "Unhandled exception in Window Manager", e); } finally { Surface.closeTransaction(); + if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i( + TAG, "<<< CLOSE TRANSACTION animateLocked"); } - if (mBulkUpdateParams != 0 || mPendingLayoutChanges != 0) { + for (int i = mPendingLayoutChanges.size() - 1; i >= 0; i--) { + if ((mPendingLayoutChanges.valueAt(i) + & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { + mPendingActions |= WALLPAPER_ACTION_PENDING; + } + } + + if (mBulkUpdateParams != 0 || mPendingLayoutChanges.size() > 0) { updateAnimToLayoutLocked(); } @@ -645,7 +651,8 @@ public class WindowAnimator { if (WindowManagerService.DEBUG_WINDOW_TRACE) { Slog.i(TAG, "!!! animate: exit mAnimating=" + mAnimating + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams) - + " mPendingLayoutChanges=" + Integer.toHexString(mPendingLayoutChanges)); + + " mPendingLayoutChanges(DEFAULT_DISPLAY)=" + + Integer.toHexString(mPendingLayoutChanges.get(Display.DEFAULT_DISPLAY))); } } @@ -705,7 +712,30 @@ public class WindowAnimator { } } - synchronized void clearPendingActions() { - mPendingActions = 0; + void clearPendingActions() { + synchronized (this) { + mPendingActions = 0; + } + } + + void setPendingLayoutChanges(final int displayId, final int changes) { + mPendingLayoutChanges.put(displayId, mPendingLayoutChanges.get(displayId) | changes); + } + + void setAppLayoutChanges(final AppWindowAnimator appAnimator, final int changes, String s) { + // Used to track which displays layout changes have been done. + SparseIntArray displays = new SparseIntArray(); + for (int i = appAnimator.mAllAppWinAnimators.size() - 1; i >= 0; i--) { + WindowStateAnimator winAnimator = appAnimator.mAllAppWinAnimators.get(i); + final int displayId = winAnimator.mWin.mDisplayContent.getDisplayId(); + if (displays.indexOfKey(displayId) < 0) { + setPendingLayoutChanges(displayId, changes); + if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { + mService.debugLayoutRepeats(s, mPendingLayoutChanges.get(displayId)); + } + // Keep from processing this display again. + displays.put(displayId, changes); + } + } } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index b7eeb69..c82fa55 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -99,7 +99,6 @@ import android.util.EventLog; import android.util.FloatMath; import android.util.Log; import android.util.SparseArray; -//import android.util.LogPrinter; import android.util.Pair; import android.util.Slog; import android.util.SparseIntArray; @@ -454,8 +453,6 @@ public class WindowManagerService extends IWindowManager.Stub int mSystemDecorLayer = 0; final Rect mScreenRect = new Rect(); - int mPendingLayoutChanges = 0; - boolean mLayoutNeeded = true; boolean mTraversalScheduled = false; boolean mDisplayFrozen = false; boolean mWaitingForConfig = false; @@ -1769,7 +1766,7 @@ public class WindowManagerService extends IWindowManager.Stub token.hidden = !visible; // Need to do a layout to ensure the wallpaper now has the // correct size. - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; } int curWallpaperIndex = token.windows.size(); @@ -2012,7 +2009,7 @@ public class WindowManagerService extends IWindowManager.Stub token.hidden = !visible; // Need to do a layout to ensure the wallpaper now has the // correct size. - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; } int curWallpaperIndex = token.windows.size(); @@ -2311,7 +2308,7 @@ public class WindowManagerService extends IWindowManager.Stub //Slog.i(TAG, "*** Running exit animation..."); win.mExiting = true; win.mRemoveOnExit = true; - mLayoutNeeded = true; + win.mDisplayContent.layoutNeeded = true; updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); performLayoutAndPlaceSurfacesLocked(); @@ -2428,7 +2425,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!mInLayout) { assignLayersLocked(windows); - mLayoutNeeded = true; + win.mDisplayContent.layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); if (win.mAppToken != null) { win.mAppToken.updateReportedVisibilityLocked(); @@ -2494,7 +2491,7 @@ public class WindowManagerService extends IWindowManager.Stub w.mGivenVisibleInsets.scale(w.mGlobalScale); w.mGivenTouchableRegion.scale(w.mGlobalScale); } - mLayoutNeeded = true; + w.mDisplayContent.layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } } @@ -2589,7 +2586,7 @@ public class WindowManagerService extends IWindowManager.Stub window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top, (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE); window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; - mLayoutNeeded = true; + window.mDisplayContent.layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } @@ -2857,7 +2854,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - mLayoutNeeded = true; + win.mDisplayContent.layoutNeeded = true; win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; if (assignLayers) { assignLayersLocked(win.getWindowList()); @@ -2947,7 +2944,7 @@ public class WindowManagerService extends IWindowManager.Stub if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) { adjustWallpaperWindowsLocked(); } - mLayoutNeeded = true; + win.mDisplayContent.layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } } @@ -3461,11 +3458,11 @@ public class WindowManagerService extends IWindowManager.Stub win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false); changed = true; + win.mDisplayContent.layoutNeeded = true; } } if (changed) { - mLayoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/); @@ -3721,7 +3718,7 @@ public class WindowManagerService extends IWindowManager.Stub if (computeScreenConfigurationLocked(mTempConfiguration)) { if (currentConfig.diff(mTempConfiguration) != 0) { mWaitingForConfig = true; - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; startFreezingDisplayLocked(false); config = new Configuration(mTempConfiguration); } @@ -3807,6 +3804,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override public int getAppOrientation(IApplicationToken token) { synchronized(mWindowMap) { AppWindowToken wtoken = findAppWindowToken(token.asBinder()); @@ -3818,6 +3816,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override public void setFocusedApp(IBinder token, boolean moveFocusNow) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setFocusedApp()")) { @@ -3855,6 +3854,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "prepareAppTransition()")) { @@ -4084,7 +4084,7 @@ public class WindowManagerService extends IWindowManager.Stub updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/); - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); Binder.restoreCallingIdentity(origId); return; @@ -4249,6 +4249,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.TRANSIT_ENTER, true); } changed = true; + win.mDisplayContent.layoutNeeded = true; } } else if (win.isVisibleNow()) { if (!runningAppAnimation) { @@ -4256,6 +4257,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowManagerPolicy.TRANSIT_EXIT, false); } changed = true; + win.mDisplayContent.layoutNeeded = true; } } @@ -4277,7 +4279,6 @@ public class WindowManagerService extends IWindowManager.Stub + wtoken.hiddenRequested); if (changed) { - mLayoutNeeded = true; mInputMonitor.setUpdateInputWindowsNeededLw(); if (performLayout) { updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, @@ -4405,6 +4406,7 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mOrientationChangeComplete = false; } unfrozeWindows = true; + w.mDisplayContent.layoutNeeded = true; } } if (force || unfrozeWindows) { @@ -4414,7 +4416,6 @@ public class WindowManagerService extends IWindowManager.Stub } if (unfreezeSurfaceNow) { if (unfrozeWindows) { - mLayoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } stopFreezingDisplayLocked(); @@ -4759,13 +4760,15 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = iterator.next(); final WindowList windows = displayContent.getWindowList(); final int pos = findWindowOffsetLocked(windows, index); - reAddAppWindowsLocked(displayContent, pos, wtoken); + final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); + if (pos != newPos) { + displayContent.layoutNeeded = true; + } } if (DEBUG_REORDER) Slog.v(TAG, "Final window list:"); if (DEBUG_REORDER) dumpWindowsLocked(); updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); - mLayoutNeeded = true; mInputMonitor.setUpdateInputWindowsNeededLw(); performLayoutAndPlaceSurfacesLocked(); mInputMonitor.updateInputWindowsLw(false /*force*/); @@ -4805,7 +4808,10 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = iterator.next(); final WindowList windows = displayContent.getWindowList(); final int pos = findWindowOffsetLocked(windows, tokenPos); - reAddAppWindowsLocked(displayContent, pos, wtoken); + final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken); + if (pos != newPos) { + displayContent.layoutNeeded = true; + } if (updateFocusAndLayout && !updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/)) { @@ -4818,7 +4824,6 @@ public class WindowManagerService extends IWindowManager.Stub // Note that the above updateFocusedWindowLocked conditional used to sit here. - mLayoutNeeded = true; if (!mInLayout) { performLayoutAndPlaceSurfacesLocked(); } @@ -4847,7 +4852,11 @@ public class WindowManagerService extends IWindowManager.Stub for (i=0; i<N; i++) { WindowToken token = mTokenMap.get(tokens.get(i)); if (token != null) { - pos = reAddAppWindowsLocked(displayContent, pos, token); + final int newPos = reAddAppWindowsLocked(displayContent, pos, token); + if (newPos != pos) { + displayContent.layoutNeeded = true; + } + pos = newPos; } } if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, @@ -4860,7 +4869,6 @@ public class WindowManagerService extends IWindowManager.Stub // Note that the above updateFocusedWindowLocked used to sit here. - mLayoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); mInputMonitor.updateInputWindowsLw(false /*force*/); @@ -5654,7 +5662,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { changed = updateRotationUncheckedLocked(false); if (!changed || forceRelayout) { - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } } @@ -5732,7 +5740,7 @@ public class WindowManagerService extends IWindowManager.Stub mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT); mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT), 2000); mWaitingForConfig = true; - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; startFreezingDisplayLocked(inTransaction); mInputManager.setDisplayOrientation(0, rotation); @@ -6390,7 +6398,8 @@ public class WindowManagerService extends IWindowManager.Stub sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh); sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw); outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density); - outConfig.screenLayout = sl; + outConfig.screenLayout = + sl|(outConfig.screenLayout&Configuration.SCREENLAYOUT_LAYOUTDIR_MASK); } private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, @@ -7576,7 +7585,7 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.setInitialDisplaySize(mDefaultDisplay, displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight, displayContent.mBaseDisplayDensity); - mLayoutNeeded = true; + displayContent.layoutNeeded = true; boolean configChanged = updateOrientationFromAppTokensLocked(false); mTempConfiguration.setToDefaults(); @@ -7831,31 +7840,11 @@ public class WindowManagerService extends IWindowManager.Stub } try { - DisplayContentsIterator iterator = new DisplayContentsIterator(); - while (iterator.hasNext()) { - final DisplayContent displayContent = iterator.next(); - performLayoutAndPlaceSurfacesLockedInner(displayContent, recoveringMemory); - - final int N = mPendingRemove.size(); - if (N > 0) { - if (mPendingRemoveTmp.length < N) { - mPendingRemoveTmp = new WindowState[N+10]; - } - mPendingRemove.toArray(mPendingRemoveTmp); - mPendingRemove.clear(); - for (int i=0; i<N; i++) { - WindowState w = mPendingRemoveTmp[i]; - removeWindowInnerLocked(w.mSession, w); - } - - assignLayersLocked(displayContent.getWindowList()); - mLayoutNeeded = true; - } - } + performLayoutAndPlaceSurfacesLockedInner(recoveringMemory); mInLayout = false; - if (mLayoutNeeded) { + if (needsLayout()) { if (++mLayoutRepeatCount < 6) { requestTraversalLocked(); } else { @@ -7880,11 +7869,11 @@ public class WindowManagerService extends IWindowManager.Stub private final void performLayoutLockedInner(final DisplayContent displayContent, boolean initial, boolean updateInputWindows) { - if (!mLayoutNeeded) { + if (!displayContent.layoutNeeded) { return; } + displayContent.layoutNeeded = false; WindowList windows = displayContent.getWindowList(); - mLayoutNeeded = false; DisplayInfo displayInfo = displayContent.getDisplayInfo(); final int dw = displayInfo.logicalWidth; @@ -7901,7 +7890,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_LAYOUT) { Slog.v(TAG, "-------------------------------------"); Slog.v(TAG, "performLayout: needed=" - + mLayoutNeeded + " dw=" + dw + " dh=" + dh); + + displayContent.layoutNeeded + " dw=" + dw + " dh=" + dh); } WindowStateAnimator universeBackground = null; @@ -8046,8 +8035,7 @@ public class WindowManagerService extends IWindowManager.Stub /** * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method. - * @param windows TODO(cmautner): - * + * @param windows List of windows on default display. * @return bitmap indicating if another pass through layout must be made. */ public int handleAppTransitionReadyLocked(WindowList windows) { @@ -8303,7 +8291,7 @@ public class WindowManagerService extends IWindowManager.Stub // a new layout to get them all up-to-date. changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; // TODO(multidisplay): IMEs are only supported on the default display. if (windows == getDefaultWindowList() && !moveInputMethodWindowsIfNeededLocked(true)) { @@ -8525,8 +8513,7 @@ public class WindowManagerService extends IWindowManager.Stub } // "Something has changed! Let's make it correct now." - private final void performLayoutAndPlaceSurfacesLockedInner( - final DisplayContent displayContent, boolean recoveringMemory) { + private final void performLayoutAndPlaceSurfacesLockedInner(boolean recoveringMemory) { if (DEBUG_WINDOW_TRACE) { Slog.v(TAG, "performLayoutAndPlaceSurfacesLockedInner: entry. Called by " + Debug.getCallers(3)); @@ -8536,13 +8523,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } - final WindowList windows = displayContent.getWindowList(); final long currentTime = SystemClock.uptimeMillis(); - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - final int dw = displayInfo.logicalWidth; - final int dh = displayInfo.logicalHeight; - final int innerDw = displayInfo.appWidth; - final int innerDh = displayInfo.appHeight; int i; @@ -8567,201 +8548,233 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mButtonBrightness = -1; mTransactionSequence++; + final DisplayContent defaultDisplay = getDefaultDisplayContent(); + final DisplayInfo defaultInfo = defaultDisplay.getDisplayInfo(); + final int defaultDw = defaultInfo.logicalWidth; + final int defaultDh = defaultInfo.logicalHeight; + final int defaultInnerDw = defaultInfo.appWidth; + final int defaultInnerDh = defaultInfo.appHeight; + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces"); - Surface.openTransaction(); try { + if (mWatermark != null) { - mWatermark.positionSurface(dw, dh); + mWatermark.positionSurface(defaultDw, defaultDh); } if (mStrictModeFlash != null) { - mStrictModeFlash.positionSurface(dw, dh); + mStrictModeFlash.positionSurface(defaultDw, defaultDh); } // Give the display manager a chance to adjust properties // like display rotation if it needs to. mDisplayManagerService.performTraversalInTransactionFromWindowManager(); - int repeats = 0; + boolean focusDisplayed = false; + boolean updateAllDrawn = false; - do { - repeats++; - if (repeats > 6) { - Slog.w(TAG, "Animation repeat aborted after too many iterations"); - mLayoutNeeded = false; - break; - } + DisplayContentsIterator iterator = new DisplayContentsIterator(); + while (iterator.hasNext()) { + final DisplayContent displayContent = iterator.next(); + WindowList windows = displayContent.getWindowList(); + DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final int displayId = displayContent.getDisplayId(); + final int dw = displayInfo.logicalWidth; + final int dh = displayInfo.logicalHeight; + final int innerDw = displayInfo.appWidth; + final int innerDh = displayInfo.appHeight; + final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); + + int repeats = 0; + do { + repeats++; + if (repeats > 6) { + Slog.w(TAG, "Animation repeat aborted after too many iterations"); + displayContent.layoutNeeded = false; + break; + } - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", - mPendingLayoutChanges); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner", + displayContent.pendingLayoutChanges); - if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) { - if ((adjustWallpaperWindowsLocked() & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { + if (isDefaultDisplay && ((displayContent.pendingLayoutChanges + & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) + && ((adjustWallpaperWindowsLocked() + & ADJUST_WALLPAPER_LAYERS_CHANGED) != 0)) { assignLayersLocked(windows); - mLayoutNeeded = true; + displayContent.layoutNeeded = true; } - } - if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); - if (updateOrientationFromAppTokensLocked(true)) { - mLayoutNeeded = true; - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + if (isDefaultDisplay && (displayContent.pendingLayoutChanges + & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout"); + if (updateOrientationFromAppTokensLocked(true)) { + displayContent.layoutNeeded = true; + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } } - } - - if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { - mLayoutNeeded = true; - } - // FIRST LOOP: Perform a layout, if needed. - if (repeats < 4) { - performLayoutLockedInner(displayContent, repeats == 1, false /*updateInputWindows*/); - } else { - Slog.w(TAG, "Layout repeat skipped after too many iterations"); - } + if ((displayContent.pendingLayoutChanges + & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { + displayContent.layoutNeeded = true; + } - // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think - // it is animating. - mPendingLayoutChanges = 0; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + mLayoutRepeatCount, - mPendingLayoutChanges); - mPolicy.beginPostLayoutPolicyLw(dw, dh); - for (i = windows.size() - 1; i >= 0; i--) { - WindowState w = windows.get(i); - if (w.mHasSurface) { - mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); + // FIRST LOOP: Perform a layout, if needed. + if (repeats < 4) { + performLayoutLockedInner(displayContent, repeats == 1, + false /*updateInputWindows*/); + } else { + Slog.w(TAG, "Layout repeat skipped after too many iterations"); } - } - mPendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw", - mPendingLayoutChanges); - } while (mPendingLayoutChanges != 0); - final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); + // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think + // it is animating. + displayContent.pendingLayoutChanges = 0; - mInnerFields.mObscured = false; - mInnerFields.mDimming = false; - mInnerFields.mSyswin = false; + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("loop number " + + mLayoutRepeatCount, displayContent.pendingLayoutChanges); - boolean focusDisplayed = false; - boolean updateAllDrawn = false; - final int N = windows.size(); - for (i=N-1; i>=0; i--) { - WindowState w = windows.get(i); + mPolicy.beginPostLayoutPolicyLw(dw, dh); + for (i = windows.size() - 1; i >= 0; i--) { + WindowState w = windows.get(i); + if (w.mHasSurface) { + mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs); + } + } + displayContent.pendingLayoutChanges |= mPolicy.finishPostLayoutPolicyLw(); + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishPostLayoutPolicyLw", + displayContent.pendingLayoutChanges); + } while (displayContent.pendingLayoutChanges != 0); - final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; + mInnerFields.mObscured = false; + mInnerFields.mDimming = false; + mInnerFields.mSyswin = false; - // Update effect. - w.mObscured = mInnerFields.mObscured; - if (!mInnerFields.mObscured) { - handleNotObscuredLocked(w, currentTime, innerDw, innerDh); - } + // Only used if default window + final boolean someoneLosingFocus = !mLosingFocus.isEmpty(); - if (obscuredChanged && (mWallpaperTarget == w) && w.isVisibleLw()) { - // This is the wallpaper target and its obscured state - // changed... make sure the current wallaper's visibility - // has been updated accordingly. - updateWallpaperVisibilityLocked(); - } + final int N = windows.size(); + for (i=N-1; i>=0; i--) { + WindowState w = windows.get(i); - final WindowStateAnimator winAnimator = w.mWinAnimator; + final boolean obscuredChanged = w.mObscured != mInnerFields.mObscured; - // If the window has moved due to its containing - // content frame changing, then we'd like to animate - // it. - if (w.mHasSurface && w.shouldAnimateMove()) { - // Frame has moved, containing content frame - // has also moved, and we're not currently animating... - // let's do something. - Animation a = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.window_move_from_decor); - winAnimator.setAnimation(a); - winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; - winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; - try { - w.mClient.moved(w.mFrame.left, w.mFrame.top); - } catch (RemoteException e) { + // Update effect. + w.mObscured = mInnerFields.mObscured; + if (!mInnerFields.mObscured) { + handleNotObscuredLocked(w, currentTime, innerDw, innerDh); } - } - //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); - w.mContentChanged = false; + if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w) + && w.isVisibleLw()) { + // This is the wallpaper target and its obscured state + // changed... make sure the current wallaper's visibility + // has been updated accordingly. + updateWallpaperVisibilityLocked(); + } - // Moved from updateWindowsAndWallpaperLocked(). - if (w.mHasSurface) { - // Take care of the window being ready to display. - if (winAnimator.commitFinishDrawingLocked(currentTime)) { - if ((w.mAttrs.flags - & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { - if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, - "First draw done in potential wallpaper target " + w); - mInnerFields.mWallpaperMayChange = true; - mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; - if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { - debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true", - mPendingLayoutChanges); - } + final WindowStateAnimator winAnimator = w.mWinAnimator; + + // If the window has moved due to its containing + // content frame changing, then we'd like to animate + // it. + if (w.mHasSurface && w.shouldAnimateMove()) { + // Frame has moved, containing content frame + // has also moved, and we're not currently animating... + // let's do something. + Animation a = AnimationUtils.loadAnimation(mContext, + com.android.internal.R.anim.window_move_from_decor); + winAnimator.setAnimation(a); + winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left; + winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top; + try { + w.mClient.moved(w.mFrame.left, w.mFrame.top); + } catch (RemoteException e) { } } - winAnimator.setSurfaceBoundaries(recoveringMemory); + //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing"); + w.mContentChanged = false; - final AppWindowToken atoken = w.mAppToken; - if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { - Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" - + w.isOnScreen() + " allDrawn=" + atoken.allDrawn - + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); - } - if (atoken != null - && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { - if (atoken.lastTransactionSequence != mTransactionSequence) { - atoken.lastTransactionSequence = mTransactionSequence; - atoken.numInterestingWindows = atoken.numDrawnWindows = 0; - atoken.startingDisplayed = false; - } - if ((w.isOnScreen() || winAnimator.mAttrType - == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) - && !w.mExiting && !w.mDestroying) { - if (WindowManagerService.DEBUG_VISIBILITY || - WindowManagerService.DEBUG_ORIENTATION) { - Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() - + ", isAnimating=" + winAnimator.isAnimating()); - if (!w.isDrawnLw()) { - Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface - + " pv=" + w.mPolicyVisibility - + " mDrawState=" + winAnimator.mDrawState - + " ah=" + w.mAttachedHidden - + " th=" + atoken.hiddenRequested - + " a=" + winAnimator.mAnimating); + // Moved from updateWindowsAndWallpaperLocked(). + if (w.mHasSurface) { + // Take care of the window being ready to display. + if (isDefaultDisplay + && winAnimator.commitFinishDrawingLocked(currentTime)) { + if ((w.mAttrs.flags + & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) { + if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG, + "First draw done in potential wallpaper target " + w); + mInnerFields.mWallpaperMayChange = true; + displayContent.pendingLayoutChanges |= + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + if (WindowManagerService.DEBUG_LAYOUT_REPEATS) { + debugLayoutRepeats( + "wallpaper and commitFinishDrawingLocked true", + displayContent.pendingLayoutChanges); } } - if (w != atoken.startingWindow) { - if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { - atoken.numInterestingWindows++; - if (w.isDrawnLw()) { - atoken.numDrawnWindows++; - if (WindowManagerService.DEBUG_VISIBILITY || - WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, - "tokenMayBeDrawn: " + atoken - + " freezingScreen=" + atoken.mAppAnimator.freezingScreen - + " mAppFreezing=" + w.mAppFreezing); - updateAllDrawn = true; + } + + winAnimator.setSurfaceBoundaries(recoveringMemory); + + final AppWindowToken atoken = w.mAppToken; + if (DEBUG_STARTING_WINDOW && atoken != null && w == atoken.startingWindow) { + Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + + w.isOnScreen() + " allDrawn=" + atoken.allDrawn + + " freezingScreen=" + atoken.mAppAnimator.freezingScreen); + } + if (atoken != null + && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) { + if (atoken.lastTransactionSequence != mTransactionSequence) { + atoken.lastTransactionSequence = mTransactionSequence; + atoken.numInterestingWindows = atoken.numDrawnWindows = 0; + atoken.startingDisplayed = false; + } + if ((w.isOnScreen() || winAnimator.mAttrType + == WindowManager.LayoutParams.TYPE_BASE_APPLICATION) + && !w.mExiting && !w.mDestroying) { + if (WindowManagerService.DEBUG_VISIBILITY || + WindowManagerService.DEBUG_ORIENTATION) { + Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw() + + ", isAnimating=" + winAnimator.isAnimating()); + if (!w.isDrawnLw()) { + Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface + + " pv=" + w.mPolicyVisibility + + " mDrawState=" + winAnimator.mDrawState + + " ah=" + w.mAttachedHidden + + " th=" + atoken.hiddenRequested + + " a=" + winAnimator.mAnimating); + } + } + if (w != atoken.startingWindow) { + if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) { + atoken.numInterestingWindows++; + if (w.isDrawnLw()) { + atoken.numDrawnWindows++; + if (WindowManagerService.DEBUG_VISIBILITY || + WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG, + "tokenMayBeDrawn: " + atoken + + " freezingScreen=" + atoken.mAppAnimator.freezingScreen + + " mAppFreezing=" + w.mAppFreezing); + updateAllDrawn = true; + } } + } else if (w.isDrawnLw()) { + atoken.startingDisplayed = true; } - } else if (w.isDrawnLw()) { - atoken.startingDisplayed = true; } } } - } - if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) { - focusDisplayed = true; - } + if (isDefaultDisplay && someoneLosingFocus && (w == mCurrentFocus) + && w.isDisplayedLw()) { + focusDisplayed = true; + } - updateResizingWindows(w); + updateResizingWindows(w); + } } if (updateAllDrawn) { @@ -8781,13 +8794,15 @@ public class WindowManagerService extends IWindowManager.Stub Surface.closeTransaction(); } + final WindowList defaultWindows = defaultDisplay.getWindowList(); + // If we are ready to perform an app transition, check through // all of the app tokens to be shown and see if they are ready // to go. if (mAppTransitionReady) { - mPendingLayoutChanges |= handleAppTransitionReadyLocked(windows); + defaultDisplay.pendingLayoutChanges |= handleAppTransitionReadyLocked(defaultWindows); if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked", - mPendingLayoutChanges); + defaultDisplay.pendingLayoutChanges); } mInnerFields.mAdjResult = 0; @@ -8799,22 +8814,22 @@ public class WindowManagerService extends IWindowManager.Stub // reflects the correct Z-order, but the window list may now // be out of sync with it. So here we will just rebuild the // entire app window list. Fun! - mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); + defaultDisplay.pendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked(); if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock", - mPendingLayoutChanges); + defaultDisplay.pendingLayoutChanges); } - if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 && - !mAppTransitionReady) { + if (mInnerFields.mWallpaperForceHidingChanged && defaultDisplay.pendingLayoutChanges == 0 + && !mAppTransitionReady) { // At this point, there was a window with a wallpaper that // was force hiding other windows behind it, but now it // is going away. This may be simple -- just animate // away the wallpaper and its window -- or it may be // hard -- the wallpaper now needs to be shown behind // something that was hidden. - mPendingLayoutChanges |= animateAwayWallpaperLocked(); + defaultDisplay.pendingLayoutChanges |= animateAwayWallpaperLocked(); if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked", - mPendingLayoutChanges); + defaultDisplay.pendingLayoutChanges); } mInnerFields.mWallpaperForceHidingChanged = false; @@ -8827,26 +8842,27 @@ public class WindowManagerService extends IWindowManager.Stub if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper layer changed: assigning layers + relayout"); - mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - assignLayersLocked(windows); + defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; + assignLayersLocked(defaultWindows); } else if ((mInnerFields.mAdjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility changed: relayout"); - mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; + defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; } if (mFocusMayChange) { mFocusMayChange = false; if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, false /*updateInputWindows*/)) { - mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM; + defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; mInnerFields.mAdjResult = 0; } } - if (mLayoutNeeded) { - mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT; - if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges); + if (needsLayout()) { + defaultDisplay.pendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; + if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", + defaultDisplay.pendingLayoutChanges); } if (!mResizingWindows.isEmpty()) { @@ -8954,11 +8970,16 @@ public class WindowManagerService extends IWindowManager.Stub mRelayoutWhileAnimating.clear(); } - if (wallpaperDestroyed) { - mLayoutNeeded |= adjustWallpaperWindowsLocked() != 0; + if (wallpaperDestroyed && (adjustWallpaperWindowsLocked() != 0)) { + getDefaultDisplayContent().layoutNeeded = true; } - if (mPendingLayoutChanges != 0) { - mLayoutNeeded = true; + + DisplayContentsIterator iterator = new DisplayContentsIterator(); + while (iterator.hasNext()) { + DisplayContent displayContent = iterator.next(); + if (displayContent.pendingLayoutChanges != 0) { + displayContent.layoutNeeded = true; + } } // Finally update all input windows now that the window changes have stabilized. @@ -8995,11 +9016,33 @@ public class WindowManagerService extends IWindowManager.Stub } } - if (mInnerFields.mOrientationChangeComplete && !mLayoutNeeded && - !mInnerFields.mUpdateRotation) { + if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded + && !mInnerFields.mUpdateRotation) { checkDrawnWindowsLocked(); } + final int N = mPendingRemove.size(); + if (N > 0) { + if (mPendingRemoveTmp.length < N) { + mPendingRemoveTmp = new WindowState[N+10]; + } + mPendingRemove.toArray(mPendingRemoveTmp); + mPendingRemove.clear(); + DisplayContentList displayList = new DisplayContentList(); + for (i = 0; i < N; i++) { + WindowState w = mPendingRemoveTmp[i]; + removeWindowInnerLocked(w.mSession, w); + if (!displayList.contains(w.mDisplayContent)) { + displayList.add(w.mDisplayContent); + } + } + + for (DisplayContent displayContent : displayList) { + assignLayersLocked(displayContent.getWindowList()); + displayContent.layoutNeeded = true; + } + } + // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. enableScreenIfNeededLocked(); @@ -9007,9 +9050,8 @@ public class WindowManagerService extends IWindowManager.Stub updateLayoutToAnimationLocked(); if (DEBUG_WINDOW_TRACE) { - Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" - + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded - + " animating=" + mAnimator.mAnimating); + Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: animating=" + + mAnimator.mAnimating); } } @@ -9165,6 +9207,16 @@ public class WindowManagerService extends IWindowManager.Stub setAnimDimParams(null); } + private boolean needsLayout() { + DisplayContentsIterator iterator = new DisplayContentsIterator(); + while (iterator.hasNext()) { + if (iterator.next().layoutNeeded) { + return true; + } + } + return false; + } + private boolean copyAnimToLayoutParamsLocked() { boolean doRequest = false; final WindowAnimator.AnimatorToLayoutParams animToLayout = mAnimator.mAnimToLayout; @@ -9197,10 +9249,15 @@ public class WindowManagerService extends IWindowManager.Stub mTurnOnScreen = true; } - mPendingLayoutChanges |= animToLayout.mPendingLayoutChanges; - if (mPendingLayoutChanges != 0) { + SparseIntArray pendingLayouts = animToLayout.mPendingLayoutChanges; + final int count = pendingLayouts.size(); + if (count > 0) { doRequest = true; } + for (int i = 0; i < count; ++i) { + final DisplayContent displayContent = getDisplayContent(pendingLayouts.keyAt(i)); + displayContent.pendingLayoutChanges = pendingLayouts.valueAt(i); + } mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper; } @@ -9336,7 +9393,7 @@ public class WindowManagerService extends IWindowManager.Stub if (moveInputMethodWindowsIfNeededLocked( mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) { - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; } if (mode == UPDATE_FOCUS_PLACING_SURFACES) { performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); @@ -9350,7 +9407,7 @@ public class WindowManagerService extends IWindowManager.Stub if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) { // The change in focus caused us to need to do a layout. Okay. - mLayoutNeeded = true; + getDefaultDisplayContent().layoutNeeded = true; if (mode == UPDATE_FOCUS_PLACING_SURFACES) { performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows); } @@ -10012,8 +10069,18 @@ public class WindowManagerService extends IWindowManager.Stub } pw.print(" mSystemBooted="); pw.print(mSystemBooted); pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); - pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); - pw.print("mTransactionSequence="); pw.println(mTransactionSequence); + if (needsLayout()) { + pw.print(" layoutNeeded on displays="); + DisplayContentsIterator dcIterator = new DisplayContentsIterator(); + while (dcIterator.hasNext()) { + final DisplayContent displayContent = dcIterator.next(); + if (displayContent.layoutNeeded) { + pw.print(displayContent.getDisplayId()); + } + } + pw.println(); + } + pw.print("mTransactionSequence="); pw.println(mTransactionSequence); pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen); pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index a52e1d7..6711445 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -587,10 +587,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { } } + @Override public int getSystemUiVisibility() { return mSystemUiVisibility; } + @Override public int getSurfaceLayer() { return mLayer; } @@ -598,7 +600,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { public IApplicationToken getAppToken() { return mAppToken != null ? mAppToken.appToken : null; } - + + public int getDisplayId() { + return mDisplayContent.getDisplayId(); + } + public long getInputDispatchingTimeoutNanos() { return mAppToken != null ? mAppToken.inputDispatchingTimeoutNanos diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 1bda22a..9bb7299 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -335,7 +335,7 @@ class WindowStateAnimator { + mWin.mPolicyVisibilityAfterAnim); } mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim; - mService.mLayoutNeeded = true; + mWin.mDisplayContent.layoutNeeded = true; if (!mWin.mPolicyVisibility) { if (mService.mCurrentFocus == mWin) { mService.mFocusMayChange = true; @@ -359,9 +359,10 @@ class WindowStateAnimator { } finishExit(); - mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; + final int displayId = mWin.mDisplayContent.getDisplayId(); + mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM); if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats( - "WindowStateAnimator", mAnimator.mPendingLayoutChanges); + "WindowStateAnimator", mAnimator.mPendingLayoutChanges.get(displayId)); if (mWin.mAppToken != null) { mWin.mAppToken.updateReportedVisibilityLocked(); @@ -1106,8 +1107,9 @@ class WindowStateAnimator { "SIZE " + width + "x" + height, null); mSurfaceResized = true; mSurface.setSize(width, height); - mAnimator.mPendingLayoutChanges |= - WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; + final int displayId = w.mDisplayContent.getDisplayId(); + mAnimator.setPendingLayoutChanges(displayId, + WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { final DisplayInfo displayInfo = mWin.mDisplayContent.getDisplayInfo(); mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount, @@ -1360,7 +1362,7 @@ class WindowStateAnimator { // do a layout. If called from within the transaction // loop, this will cause it to restart with a new // layout. - mService.mLayoutNeeded = true; + c.mDisplayContent.layoutNeeded = true; } } } diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index 9004e10..5c9282e 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -370,6 +370,13 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + throw new UnsupportedOperationException(); + } + @Override public void unregisterReceiver(BroadcastReceiver receiver) { throw new UnsupportedOperationException(); diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 46b8a27..438a670 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -183,6 +183,13 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value) return 0; } + // layout direction + if (getLayoutDirectionName(part.string(), &config)) { + *axis = AXIS_LAYOUTDIR; + *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR); + return 0; + } + // smallest screen dp width if (getSmallestScreenWidthDpName(part.string(), &config)) { *axis = AXIS_SMALLESTSCREENWIDTHDP; @@ -309,6 +316,8 @@ AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis) case AXIS_LANGUAGE: return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16) | (((uint32_t)config.language[1]) << 8) | (config.language[0]); + case AXIS_LAYOUTDIR: + return config.screenLayout&ResTable_config::MASK_LAYOUTDIR; case AXIS_SCREENLAYOUTSIZE: return config.screenLayout&ResTable_config::MASK_SCREENSIZE; case AXIS_ORIENTATION: @@ -364,7 +373,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) Vector<String8> parts; String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den; - String8 touch, key, keysHidden, nav, navHidden, size, vers; + String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers; String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp; const char *p = dir; @@ -452,6 +461,18 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) //printf("not region: %s\n", part.string()); } + if (getLayoutDirectionName(part.string())) { + layoutDir = part; + + index++; + if (index == N) { + goto success; + } + part = parts[index]; + } else { + //printf("not layout direction: %s\n", part.string()); + } + if (getSmallestScreenWidthDpName(part.string())) { smallestwidthdp = part; @@ -674,6 +695,7 @@ success: this->navHidden = navHidden; this->navigation = nav; this->screenSize = size; + this->layoutDirection = layoutDir; this->version = vers; // what is this anyway? @@ -691,6 +713,8 @@ AaptGroupEntry::toString() const s += ","; s += this->locale; s += ","; + s += layoutDirection; + s += ","; s += smallestScreenWidthDp; s += ","; s += screenWidthDp; @@ -747,6 +771,12 @@ AaptGroupEntry::toDirName(const String8& resType) const } s += locale; } + if (this->layoutDirection != "") { + if (s.length() > 0) { + s += "-"; + } + s += layoutDirection; + } if (this->smallestScreenWidthDp != "") { if (s.length() > 0) { s += "-"; @@ -958,6 +988,28 @@ bool AaptGroupEntry::getLocaleName(const char* fileName, return false; } +bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out) +{ + if (strcmp(name, kWildcardName) == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) + | ResTable_config::LAYOUTDIR_ANY; + return true; + } else if (strcmp(name, "ltr") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) + | ResTable_config::LAYOUTDIR_LTR; + return true; + } else if (strcmp(name, "rtl") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_LAYOUTDIR) + | ResTable_config::LAYOUTDIR_RTL; + return true; + } + + return false; +} + bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, ResTable_config* out) { @@ -1415,6 +1467,7 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const int v = mcc.compare(o.mcc); if (v == 0) v = mnc.compare(o.mnc); if (v == 0) v = locale.compare(o.locale); + if (v == 0) v = layoutDirection.compare(o.layoutDirection); if (v == 0) v = vendor.compare(o.vendor); if (v == 0) v = smallestScreenWidthDp.compare(o.smallestScreenWidthDp); if (v == 0) v = screenWidthDp.compare(o.screenWidthDp); @@ -1447,6 +1500,7 @@ const ResTable_config& AaptGroupEntry::toParams() const getMccName(mcc.string(), ¶ms); getMncName(mnc.string(), ¶ms); getLocaleName(locale.string(), ¶ms); + getLayoutDirectionName(layoutDirection.string(), ¶ms); getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), ¶ms); getScreenWidthDpName(screenWidthDp.string(), ¶ms); getScreenHeightDpName(screenHeightDp.string(), ¶ms); diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index d5f296c..5cfa913 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -51,6 +51,7 @@ enum { AXIS_SMALLESTSCREENWIDTHDP, AXIS_SCREENWIDTHDP, AXIS_SCREENHEIGHTDP, + AXIS_LAYOUTDIR, AXIS_VERSION, AXIS_START = AXIS_MCC, @@ -95,6 +96,7 @@ public: static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL); static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL); static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL); + static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL); static bool getVersionName(const char* name, ResTable_config* out = NULL); int compare(const AaptGroupEntry& o) const; @@ -133,6 +135,7 @@ private: String8 navHidden; String8 navigation; String8 screenSize; + String8 layoutDirection; String8 version; mutable bool mParamsChanged; diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index d98fe65..3d7b088 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -2811,7 +2811,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest) NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c " "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp\n", + "sw%ddp w%ddp h%ddp dir:%d\n", ti+1, config.mcc, config.mnc, config.language[0] ? config.language[0] : '-', @@ -2829,7 +2829,8 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest) config.screenHeight, config.smallestScreenWidthDp, config.screenWidthDp, - config.screenHeightDp)); + config.screenHeightDp, + config.layoutDirection)); if (filterable && !filter.match(config)) { continue; @@ -2853,7 +2854,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest) tHeader->config = config; NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c " "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp\n", + "sw%ddp w%ddp h%ddp dir:%d\n", ti+1, tHeader->config.mcc, tHeader->config.mnc, tHeader->config.language[0] ? tHeader->config.language[0] : '-', @@ -2871,7 +2872,8 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest) tHeader->config.screenHeight, tHeader->config.smallestScreenWidthDp, tHeader->config.screenWidthDp, - tHeader->config.screenHeightDp)); + tHeader->config.screenHeightDp, + tHeader->config.layoutDirection)); tHeader->config.swapHtoD(); // Build the entries inside of this type. @@ -3489,7 +3491,7 @@ sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry, if (config != NULL) { NOISY(printf("New entry at %s:%d: imsi:%d/%d lang:%c%c cnt:%c%c " "orien:%d touch:%d density:%d key:%d inp:%d nav:%d sz:%dx%d " - "sw%ddp w%ddp h%ddp\n", + "sw%ddp w%ddp h%ddp dir:%d\n", sourcePos.file.string(), sourcePos.line, config->mcc, config->mnc, config->language[0] ? config->language[0] : '-', @@ -3506,7 +3508,8 @@ sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry, config->screenHeight, config->smallestScreenWidthDp, config->screenWidthDp, - config->screenHeightDp)); + config->screenHeightDp, + config->layoutDirection)); } else { NOISY(printf("New entry at %s:%d: NULL config\n", sourcePos.file.string(), sourcePos.line)); diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java index bd332a6..26cb97b 100644 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java @@ -31,6 +31,7 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; */ public class SystemClock_Delegate { private static long sBootTime = System.currentTimeMillis(); + private static long sBootTimeNano = System.nanoTime(); @LayoutlibDelegate /*package*/ static boolean setCurrentTimeMillis(long millis) { @@ -60,6 +61,16 @@ public class SystemClock_Delegate { } /** + * Returns nanoseconds since boot, including time spent in sleep. + * + * @return elapsed nanoseconds since boot. + */ + @LayoutlibDelegate + /*package*/ static long elapsedRealtimeNano() { + return System.nanoTime() - sBootTimeNano; + } + + /** * Returns milliseconds running in the current thread. * * @return elapsed milliseconds in the thread diff --git a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java index 1df78c2..8b4c60b 100644 --- a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java +++ b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java @@ -91,4 +91,42 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; /*package*/ static float sqrt(float value) { return (float)Math.sqrt(value); } + + /** + * Returns the closest float approximation of the raising "e" to the power + * of the argument. + * + * @param value to compute the exponential of + * @return the exponential of value + */ + @LayoutlibDelegate + /*package*/ static float exp(float value) { + return (float)Math.exp(value); + } + + /** + * Returns the closest float approximation of the result of raising {@code + * x} to the power of {@code y}. + * + * @param x the base of the operation. + * @param y the exponent of the operation. + * @return {@code x} to the power of {@code y}. + */ + @LayoutlibDelegate + /*package*/ static float pow(float x, float y) { + return (float)Math.pow(x, y); + } + + /** + * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i> + * {@code y}</i><sup>{@code 2}</sup>{@code )}. + * + * @param x a float number + * @param y a float number + * @return the hypotenuse + */ + @LayoutlibDelegate + /*package*/ static float hypot(float x, float y) { + return (float)Math.sqrt(x*x + y*y); + } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index e629b75..428c4c2 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1164,6 +1164,13 @@ public final class BridgeContext extends Context { } @Override + public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5, + IntentFilter arg1, String arg2, Handler arg3) { + // pass + return null; + } + + @Override public void removeStickyBroadcast(Intent arg0) { // pass |