diff options
119 files changed, 2027 insertions, 784 deletions
diff --git a/Android.mk b/Android.mk index 2017404a63ef..f875be23a8a9 100644 --- a/Android.mk +++ b/Android.mk @@ -472,7 +472,8 @@ LOCAL_AIDL_INCLUDES += \  LOCAL_AIDL_INCLUDES += \  	frameworks/av/camera/aidl \ -	frameworks/native/aidl/gui +	frameworks/native/aidl/gui \ +	system/netd/server/binder  LOCAL_INTERMEDIATE_SOURCES := \  			$(framework_res_source_path)/android/R.java \ @@ -688,6 +689,7 @@ aidl_files := \  	frameworks/base/core/java/android/database/CursorWindow.aidl \  	frameworks/base/core/java/android/service/quicksettings/Tile.aidl \  	frameworks/native/aidl/binder/android/os/PersistableBundle.aidl \ +	system/netd/server/binder/android/net/UidRange.aidl \  gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl  $(gen): PRIVATE_SRC_FILES := $(aidl_files) diff --git a/api/current.txt b/api/current.txt index 535ab0107ab6..a04ecfb26d13 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29527,7 +29527,7 @@ package android.os.health {      field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726      field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b      field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e -    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750 +    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750      field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728      field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b      field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740 @@ -29539,11 +29539,11 @@ package android.os.health {      field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d      field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711      field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713 -    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f +    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f      field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f      field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712      field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714 -    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e +    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e      field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d      field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720      field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f diff --git a/api/system-current.txt b/api/system-current.txt index 1909ed995af6..dd2f18b0b9f6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -32024,7 +32024,7 @@ package android.os.health {      field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726      field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b      field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e -    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750 +    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750      field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728      field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b      field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740 @@ -32036,11 +32036,11 @@ package android.os.health {      field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d      field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711      field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713 -    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f +    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f      field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f      field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712      field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714 -    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e +    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e      field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d      field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720      field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f diff --git a/api/test-current.txt b/api/test-current.txt index 2ccf37ad754d..d056f7d57fce 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -29596,7 +29596,7 @@ package android.os.health {      field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726      field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b      field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e -    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750 +    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750      field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728      field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b      field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740 @@ -29608,11 +29608,11 @@ package android.os.health {      field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d      field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711      field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713 -    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f +    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = 10063; // 0x274f      field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f      field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712      field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714 -    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e +    field public static final int MEASUREMENT_USER_CPU_TIME_MS = 10062; // 0x274e      field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d      field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720      field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java index b83484d99824..31c742153f24 100644 --- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java +++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java @@ -44,6 +44,7 @@ public final class Dpm extends BaseCommand {      private static final String COMMAND_SET_ACTIVE_ADMIN = "set-active-admin";      private static final String COMMAND_SET_DEVICE_OWNER = "set-device-owner";      private static final String COMMAND_SET_PROFILE_OWNER = "set-profile-owner"; +    private static final String COMMAND_REMOVE_ACTIVE_ADMIN = "remove-active-admin";      private IDevicePolicyManager mDevicePolicyManager;      private int mUserId = UserHandle.USER_SYSTEM; @@ -60,6 +61,8 @@ public final class Dpm extends BaseCommand {                  "[ --name <NAME> ] <COMPONENT>\n" +                  "usage: dpm set-profile-owner [ --user <USER_ID> | current ] [ --name <NAME> ] " +                  "<COMPONENT>\n" + +                "usage: dpm remove-active-admin [ --user <USER_ID> | current ] [ --name <NAME> ] " + +                "<COMPONENT>\n" +                  "\n" +                  "dpm set-active-admin: Sets the given component as active admin" +                  " for an existing user.\n" + @@ -68,7 +71,11 @@ public final class Dpm extends BaseCommand {                  " package as device owner.\n" +                  "\n" +                  "dpm set-profile-owner: Sets the given component as active admin and profile" + -                " owner for an existing user.\n"); +                " owner for an existing user.\n" + +                "\n" + +                "dpm remove-active-admin: Disables an active admin, the admin must have declared" + +                " android:testOnly in the application in its manifest. This will also remove" + +                " device and profile owners\n");      }      @Override @@ -91,6 +98,9 @@ public final class Dpm extends BaseCommand {              case COMMAND_SET_PROFILE_OWNER:                  runSetProfileOwner();                  break; +            case COMMAND_REMOVE_ACTIVE_ADMIN: +                runRemoveActiveAdmin(); +                break;              default:                  throw new IllegalArgumentException ("unknown command '" + command + "'");          } @@ -152,6 +162,12 @@ public final class Dpm extends BaseCommand {          System.out.println("Active admin set to component " + mComponent.toShortString());      } +    private void runRemoveActiveAdmin() throws RemoteException { +        parseArgs(/*canHaveName=*/ false); +        mDevicePolicyManager.forceRemoveActiveAdmin(mComponent, mUserId); +        System.out.println("Success: Admin removed " + mComponent); +    } +      private void runSetProfileOwner() throws RemoteException {          parseArgs(/*canHaveName=*/ true);          mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId); diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index e788d2749d17..8ff38bb8647b 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -559,7 +559,8 @@ public final class AnimatorSet extends Animator {          boolean previouslyPaused = mPaused;          super.pause();          if (!previouslyPaused && mPaused) { -            if (mDelayAnim != null) { +            if (mDelayAnim.isStarted()) { +                // If delay hasn't passed, pause the start delay animator.                  mDelayAnim.pause();              } else {                  int size = mNodes.size(); @@ -578,7 +579,8 @@ public final class AnimatorSet extends Animator {          boolean previouslyPaused = mPaused;          super.resume();          if (previouslyPaused && !mPaused) { -            if (mDelayAnim != null) { +            if (mDelayAnim.isStarted()) { +                // If start delay hasn't passed, resume the previously paused start delay animator                  mDelayAnim.resume();              } else {                  int size = mNodes.size(); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index ee4c2f7b5ca7..4b8d9ee37cc6 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -139,4 +139,9 @@ public abstract class ActivityManagerInternal {       * minimized state.       */      public abstract void notifyDockedStackMinimizedChanged(boolean minimized); + +    /** +     * Kill foreground apps from the specified user. +     */ +    public abstract void killForegroundAppsForUser(int userHandle);  } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 7a18df6e4e44..0ca2e14ade47 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -6391,6 +6391,24 @@ public class DevicePolicyManager {          }      } +    /** +     * @hide +     * Remove a test admin synchronously without sending it a broadcast about being removed. +     * If the admin is a profile owner or device owner it will still be removed. +     * +     * @param userHandle user id to remove the admin for. +     * @param admin The administration compononent to remove. +     * @throws SecurityException if the caller is not shell / root or the admin package +     *         isn't a test application see {@link ApplicationInfo#FLAG_TEST_APP}. +     */ +    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) { +        try { +            mService.forceRemoveActiveAdmin(adminReceiver, userHandle); +        } catch (RemoteException re) { +            throw re.rethrowFromSystemServer(); +        } +    } +      private void throwIfParentInstance(String functionName) {          if (mParentInstance) {              throw new SecurityException(functionName + " cannot be called on the parent instance"); diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index cba64c2ef48a..989e61341363 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -111,6 +111,7 @@ interface IDevicePolicyManager {      boolean packageHasActiveAdmins(String packageName, int userHandle);      void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);      void removeActiveAdmin(in ComponentName policyReceiver, int userHandle); +    void forceRemoveActiveAdmin(in ComponentName policyReceiver, int userHandle);      boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy, int userHandle);      void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java index 70d47ee20b2e..8e659e04d705 100644 --- a/core/java/android/bluetooth/OobData.java +++ b/core/java/android/bluetooth/OobData.java @@ -22,7 +22,11 @@ import android.os.Parcelable;  import android.util.Log;  /** - * Out Of Band Data for Bluetooth device. + * Out Of Band Data for Bluetooth device pairing. + * + * <p>This object represents optional data obtained from a remote device through + * an out-of-band channel (eg. NFC). + *   * @hide   */  public class OobData implements Parcelable { @@ -32,6 +36,11 @@ public class OobData implements Parcelable {          return securityManagerTk;      } +    /** +     * Sets the Temporary Key value to be used by the LE Security Manager during +     * LE pairing. The value shall be 16 bytes. Please see Bluetooth CSSv6, +     * Part A 1.8 for a detailed description. +     */      public void setSecurityManagerTk(byte[] securityManagerTk) {          this.securityManagerTk = securityManagerTk;      } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 15cc17da2150..8349d3da6860 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2446,6 +2446,15 @@ public abstract class Context {       * <p>This function will throw {@link SecurityException} if you do not       * have permission to start the given service.       * +     * <p class="note"><strong>Note:</strong> Each call to startService() +     * results in significant work done by the system to manage service +     * lifecycle surrounding the processing of the intent, which can take +     * multiple milliseconds of CPU time. Due to this cost, startService() +     * should not be used for frequent intent delivery to a service, and only +     * for scheduling significant work. Use {@link #bindService bound services} +     * for high frequency calls. +     * </p> +     *       * @param service Identifies the service to be started.  The Intent must be either       *      fully explicit (supplying a component name) or specify a specific package       *      name it is targetted to.  Additional values diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 4108f6dea139..bb8bca414ed1 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -131,12 +131,6 @@ public class PackageParser {      /** File name in an APK for the Android manifest. */      private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml"; -    /** -     * File name in an APK for bytecode.  There may be additional bytecode files -     * but this one is always required for an APK that has code. -     */ -    private static final String BYTECODE_FILENAME = "classes.dex"; -      /** Path prefix for apps on expanded storage */      private static final String MNT_EXPAND = "/mnt/expand/"; @@ -1137,13 +1131,11 @@ public class PackageParser {          Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");          try { -            collectCertificates( -                    pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags); +            collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);              if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {                  for (int i = 0; i < pkg.splitCodePaths.length; i++) { -                    collectCertificates( -                            pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i], parseFlags); +                    collectCertificates(pkg, new File(pkg.splitCodePaths[i]), parseFlags);                  }              }          } finally { @@ -1151,10 +1143,8 @@ public class PackageParser {          }      } -    private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags) +    private static void collectCertificates(Package pkg, File apkFile, int parseFlags)              throws PackageParserException { -        final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0; -        final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode;          final String apkPath = apkFile.getAbsolutePath();          // Try to verify the APK using APK Signature Scheme v2. @@ -1202,7 +1192,6 @@ public class PackageParser {              }          } -        boolean codeFound = false;          StrictJarFile jarFile = null;          try {              Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "strictJarFileCtor"); @@ -1226,10 +1215,6 @@ public class PackageParser {              // Optimization: early termination when APK already verified              if (verified) { -                if ((requireCode) && (jarFile.findEntry(BYTECODE_FILENAME) == null)) { -                    throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, -                            "Package " + apkPath + " code is missing"); -                }                  return;              } @@ -1249,19 +1234,11 @@ public class PackageParser {                      final String entryName = entry.getName();                      if (entryName.startsWith("META-INF/")) continue;                      if (entryName.equals(ANDROID_MANIFEST_FILENAME)) continue; -                    if (entryName.equals(BYTECODE_FILENAME)) { -                        codeFound = true; -                    }                      toVerify.add(entry);                  }              } -            if (!codeFound && requireCode) { -                throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, -                        "Package " + apkPath + " code is missing"); -            } -              // Verify that entries are signed consistently with the first entry              // we encountered. Note that for splits, certificates may have              // already been populated during an earlier parse of a base APK. @@ -1349,7 +1326,7 @@ public class PackageParser {                  final Package tempPkg = new Package(null);                  Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");                  try { -                    collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/, 0 /*flags*/); +                    collectCertificates(tempPkg, apkFile, 0 /*parseFlags*/);                  } finally {                      Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);                  } diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java index c7d257fcaa42..337235a38bde 100644 --- a/core/java/android/os/health/UidHealthStats.java +++ b/core/java/android/os/health/UidHealthStats.java @@ -261,16 +261,16 @@ public final class UidHealthStats {      public static final int TIMER_MOBILE_RADIO_ACTIVE = HealthKeys.BASE_UID + 61;      @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT) -    public static final int MEASUREMENT_USER_CPU_TIME_US = HealthKeys.BASE_UID + 62; +    public static final int MEASUREMENT_USER_CPU_TIME_MS = HealthKeys.BASE_UID + 62;      @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT) -    public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = HealthKeys.BASE_UID + 63; +    public static final int MEASUREMENT_SYSTEM_CPU_TIME_MS = HealthKeys.BASE_UID + 63;      /**       * An estimate of the number of milliamp-microsends used by this uid.       */      @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT) -    public static final int MEASUREMENT_CPU_POWER_MAUS = HealthKeys.BASE_UID + 64; +    public static final int MEASUREMENT_CPU_POWER_MAMS = HealthKeys.BASE_UID + 64;      /**       * @hide diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java index c0f0663084fe..b62cc66b5269 100644 --- a/core/java/android/text/Emoji.java +++ b/core/java/android/text/Emoji.java @@ -24,6 +24,122 @@ import java.util.Arrays;   */  public class Emoji {      // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt +    // TODO: Generate from external/unicode/emoji-data.txt +    private static int[] EMOJI_LIST = { +        0x0023, 0x002A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, +        0x0039, 0x00A9, 0x00AE, 0x203C, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, +        0x2198, 0x2199, 0x21A9, 0x21AA, 0x231A, 0x231B, 0x2328, 0x23CF, 0x23E9, 0x23EA, 0x23EB, +        0x23EC, 0x23ED, 0x23EE, 0x23EF, 0x23F0, 0x23F1, 0x23F2, 0x23F3, 0x23F8, 0x23F9, 0x23FA, +        0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600, 0x2601, +        0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622, +        0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A, +        0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663, +        0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699, +        0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4, +        0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1, +        0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2705, +        0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716, 0x271D, +        0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E, 0x2753, 0x2754, 0x2755, +        0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0, 0x27BF, 0x2934, 0x2935, +        0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299, +        0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E, 0x1F191, 0x1F192, 0x1F193, +        0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A, 0x1F1E6, 0x1F1E7, 0x1F1E8, +        0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1F2, +        0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9, 0x1F1FA, 0x1F1FB, 0x1F1FC, +        0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F, 0x1F232, 0x1F233, 0x1F234, +        0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250, 0x1F251, 0x1F300, 0x1F301, +        0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308, 0x1F309, 0x1F30A, 0x1F30B, +        0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312, 0x1F313, 0x1F314, 0x1F315, +        0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C, 0x1F31D, 0x1F31E, 0x1F31F, +        0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B, +        0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332, 0x1F333, 0x1F334, 0x1F335, +        0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C, 0x1F33D, 0x1F33E, 0x1F33F, +        0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346, 0x1F347, 0x1F348, 0x1F349, +        0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350, 0x1F351, 0x1F352, 0x1F353, +        0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A, 0x1F35B, 0x1F35C, 0x1F35D, +        0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364, 0x1F365, 0x1F366, 0x1F367, +        0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E, 0x1F36F, 0x1F370, 0x1F371, +        0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378, 0x1F379, 0x1F37A, 0x1F37B, +        0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382, 0x1F383, 0x1F384, 0x1F385, +        0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C, 0x1F38D, 0x1F38E, 0x1F38F, +        0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E, +        0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5, 0x1F3A6, 0x1F3A7, 0x1F3A8, +        0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF, 0x1F3B0, 0x1F3B1, 0x1F3B2, +        0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9, 0x1F3BA, 0x1F3BB, 0x1F3BC, +        0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3, 0x1F3C4, 0x1F3C5, 0x1F3C6, +        0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD, 0x1F3CE, 0x1F3CF, 0x1F3D0, +        0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA, +        0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1, 0x1F3E2, 0x1F3E3, 0x1F3E4, +        0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3ED, 0x1F3EE, +        0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8, 0x1F3F9, 0x1F3FA, 0x1F3FB, +        0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402, 0x1F403, 0x1F404, 0x1F405, +        0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C, 0x1F40D, 0x1F40E, 0x1F40F, +        0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416, 0x1F417, 0x1F418, 0x1F419, +        0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420, 0x1F421, 0x1F422, 0x1F423, +        0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A, 0x1F42B, 0x1F42C, 0x1F42D, +        0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434, 0x1F435, 0x1F436, 0x1F437, +        0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E, 0x1F43F, 0x1F440, 0x1F441, +        0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B, +        0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452, 0x1F453, 0x1F454, 0x1F455, +        0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C, 0x1F45D, 0x1F45E, 0x1F45F, +        0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466, 0x1F467, 0x1F468, 0x1F469, +        0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470, 0x1F471, 0x1F472, 0x1F473, +        0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A, 0x1F47B, 0x1F47C, 0x1F47D, +        0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484, 0x1F485, 0x1F486, 0x1F487, +        0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E, 0x1F48F, 0x1F490, 0x1F491, +        0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498, 0x1F499, 0x1F49A, 0x1F49B, +        0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2, 0x1F4A3, 0x1F4A4, 0x1F4A5, +        0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC, 0x1F4AD, 0x1F4AE, 0x1F4AF, +        0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6, 0x1F4B7, 0x1F4B8, 0x1F4B9, +        0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0, 0x1F4C1, 0x1F4C2, 0x1F4C3, +        0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA, 0x1F4CB, 0x1F4CC, 0x1F4CD, +        0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4, 0x1F4D5, 0x1F4D6, 0x1F4D7, +        0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE, 0x1F4DF, 0x1F4E0, 0x1F4E1, +        0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8, 0x1F4E9, 0x1F4EA, 0x1F4EB, +        0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2, 0x1F4F3, 0x1F4F4, 0x1F4F5, +        0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC, 0x1F4FD, 0x1F4FF, 0x1F500, +        0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507, 0x1F508, 0x1F509, 0x1F50A, +        0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511, 0x1F512, 0x1F513, 0x1F514, +        0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B, 0x1F51C, 0x1F51D, 0x1F51E, +        0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525, 0x1F526, 0x1F527, 0x1F528, +        0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F, 0x1F530, 0x1F531, 0x1F532, +        0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539, 0x1F53A, 0x1F53B, 0x1F53C, +        0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E, 0x1F550, 0x1F551, 0x1F552, +        0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559, 0x1F55A, 0x1F55B, 0x1F55C, +        0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563, 0x1F564, 0x1F565, 0x1F566, +        0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578, 0x1F579, +        0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F595, 0x1F596, 0x1F5A4, +        0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2, +        0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA, +        0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601, 0x1F602, 0x1F603, 0x1F604, +        0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B, 0x1F60C, 0x1F60D, 0x1F60E, +        0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615, 0x1F616, 0x1F617, 0x1F618, +        0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F, 0x1F620, 0x1F621, 0x1F622, +        0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629, 0x1F62A, 0x1F62B, 0x1F62C, +        0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633, 0x1F634, 0x1F635, 0x1F636, +        0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D, 0x1F63E, 0x1F63F, 0x1F640, +        0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647, 0x1F648, 0x1F649, 0x1F64A, +        0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681, 0x1F682, 0x1F683, 0x1F684, +        0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B, 0x1F68C, 0x1F68D, 0x1F68E, +        0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695, 0x1F696, 0x1F697, 0x1F698, +        0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F, 0x1F6A0, 0x1F6A1, 0x1F6A2, +        0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9, 0x1F6AA, 0x1F6AB, 0x1F6AC, +        0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3, 0x1F6B4, 0x1F6B5, 0x1F6B6, +        0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD, 0x1F6BE, 0x1F6BF, 0x1F6C0, +        0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC, 0x1F6CD, 0x1F6CE, 0x1F6CF, +        0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9, +        0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6, 0x1F910, 0x1F911, 0x1F912, +        0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919, 0x1F91A, 0x1F91B, 0x1F91C, +        0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924, 0x1F925, 0x1F926, 0x1F927, +        0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, 0x1F939, 0x1F93A, 0x1F93B, +        0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943, 0x1F944, 0x1F945, 0x1F946, +        0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951, 0x1F952, 0x1F953, 0x1F954, +        0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B, 0x1F95C, 0x1F95D, 0x1F95E, +        0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986, 0x1F987, 0x1F988, 0x1F989, +        0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990, 0x1F991, 0x1F9C0 +    }; + +    // See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt      private static int[] EMOJI_MODIFIER_BASE = {          0x261D, 0x26F9, 0x270A, 0x270B, 0x270C, 0x270D, 0x1F385, 0x1F3C3, 0x1F3C4, 0x1F3CA,          0x1F3CB, 0x1F442, 0x1F443, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B, 0x1F44C, @@ -62,9 +178,9 @@ public class Emoji {          return Arrays.binarySearch(EMOJI_MODIFIER_BASE, codePoint) >= 0;      } -    // Returns true if the character appears before or after zwj in a zwj emoji sequence. -    public static boolean isZwjEmoji(int codePoint) { -        return Arrays.binarySearch(ZWJ_EMOJI, codePoint) >= 0; +    // Returns true if the character has Emoji property. +    public static boolean isEmoji(int codePoint) { +        return Arrays.binarySearch(EMOJI_LIST, codePoint) >= 0;      }      // Returns true if the character can be a base character of COMBINING ENCLOSING KEYCAP. diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java index e93e58da20d6..3770a45d2172 100644 --- a/core/java/android/text/method/BaseKeyListener.java +++ b/core/java/android/text/method/BaseKeyListener.java @@ -162,14 +162,14 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener                          state = STATE_LF;                      } else if (isVariationSelector(codePoint)) {                          state = STATE_BEFORE_VS; -                    } else if (Emoji.isZwjEmoji(codePoint)) { -                        state = STATE_BEFORE_ZWJ_EMOJI;                      } else if (Emoji.isRegionalIndicatorSymbol(codePoint)) {                          state = STATE_ODD_NUMBERED_RIS;                      } else if (Emoji.isEmojiModifier(codePoint)) {                          state = STATE_BEFORE_EMOJI_MODIFIER;                      } else if (codePoint == Emoji.COMBINING_ENCLOSING_KEYCAP) {                          state = STATE_BEFORE_KEYCAP; +                    } else if (Emoji.isEmoji(codePoint)) { +                        state = STATE_BEFORE_ZWJ_EMOJI;                      } else {                          state = STATE_FINISHED;                      } @@ -230,7 +230,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener                      state = STATE_FINISHED;                      break;                  case STATE_BEFORE_VS: -                    if (Emoji.isZwjEmoji(codePoint)) { +                    if (Emoji.isEmoji(codePoint)) {                          deleteCharCount += Character.charCount(codePoint);                          state = STATE_BEFORE_ZWJ_EMOJI;                          break; @@ -250,7 +250,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener                      }                      break;                  case STATE_BEFORE_ZWJ: -                    if (Emoji.isZwjEmoji(codePoint)) { +                    if (Emoji.isEmoji(codePoint)) {                          deleteCharCount += Character.charCount(codePoint) + 1;  // +1 for ZWJ.                          state = STATE_BEFORE_ZWJ_EMOJI;                      } else if (isVariationSelector(codePoint)) { @@ -261,7 +261,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener                      }                      break;                  case STATE_BEFORE_VS_AND_ZWJ: -                    if (Emoji.isZwjEmoji(codePoint)) { +                    if (Emoji.isEmoji(codePoint)) {                          // +1 for ZWJ.                          deleteCharCount += lastSeenVSCharCount + 1 + Character.charCount(codePoint);                          lastSeenVSCharCount = 0; diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index ef50fdc5eb4f..7da849a832e4 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -102,13 +102,13 @@ public class Surface implements Parcelable {      public @interface ScalingMode {}      // From system/window.h      /** @hide */ -    static final int SCALING_MODE_FREEZE = 0; +    public static final int SCALING_MODE_FREEZE = 0;      /** @hide */ -    static final int SCALING_MODE_SCALE_TO_WINDOW = 1; +    public static final int SCALING_MODE_SCALE_TO_WINDOW = 1;      /** @hide */ -    static final int SCALING_MODE_SCALE_CROP = 2; +    public static final int SCALING_MODE_SCALE_CROP = 2;      /** @hide */ -    static final int SCALING_MODE_NO_SCALE_CROP = 3; +    public static final int SCALING_MODE_NO_SCALE_CROP = 3;      /** @hide */      @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index c30ede37a4ac..dc9014be1646 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -85,6 +85,8 @@ public class SurfaceControl {              IBinder displayToken, int mode);      private static native void nativeDeferTransactionUntil(long nativeObject,              IBinder handle, long frame); +    private static native void nativeSetOverrideScalingMode(long nativeObject, +            int scalingMode);      private static native IBinder nativeGetHandle(long nativeObject); @@ -376,6 +378,11 @@ public class SurfaceControl {          nativeDeferTransactionUntil(mNativeObject, handle, frame);      } +    public void setOverrideScalingMode(int scalingMode) { +        checkNotReleased(); +        nativeSetOverrideScalingMode(mNativeObject, scalingMode); +    } +      public IBinder getHandle() {          return nativeGetHandle(mNativeObject);      } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e9ca62333daa..9e4f26fe0aec 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2716,11 +2716,11 @@ public final class ViewRootImpl implements ViewParent,                      mAttachInfo.mHardwareRenderer.setStopped(false);                  } -                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this); -                  if (updated) {                      requestDrawWindow();                  } + +                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);              } else {                  // If we get here with a disabled & requested hardware renderer, something went                  // wrong (an invalidate posted right before we destroyed the hardware surface diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 10afdb8ef109..250d9b77473d 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -60,6 +60,7 @@ import android.util.TimeUtils;  import android.util.Xml;  import android.view.Display; +import com.android.internal.annotations.VisibleForTesting;  import com.android.internal.net.NetworkStatsFactory;  import com.android.internal.util.ArrayUtils;  import com.android.internal.util.FastPrintWriter; @@ -1092,7 +1093,7 @@ public class BatteryStatsImpl extends BatteryStats {          public void writeToParcel(Parcel out, long elapsedRealtimeUs) {              if (DEBUG) Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime="                      + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); -            out.writeInt(mCount); +            out.writeInt(computeCurrentCountLocked());              out.writeInt(mLoadedCount);              out.writeInt(mUnpluggedCount);              out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); @@ -1109,7 +1110,7 @@ public class BatteryStatsImpl extends BatteryStats {                          + " old mUnpluggedCount=" + mUnpluggedCount);              }              mUnpluggedTime = computeRunTimeLocked(baseRealtime); -            mUnpluggedCount = mCount; +            mUnpluggedCount = computeCurrentCountLocked();              if (DEBUG && mType < 0) {                  Log.v(TAG, "unplug #" + mType                          + ": new mUnpluggedTime=" + mUnpluggedTime @@ -1192,7 +1193,7 @@ public class BatteryStatsImpl extends BatteryStats {          public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {              long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));              out.writeLong(runTime); -            out.writeInt(mCount); +            out.writeInt(computeCurrentCountLocked());          }          public void readSummaryFromParcelLocked(Parcel in) { @@ -1249,7 +1250,8 @@ public class BatteryStatsImpl extends BatteryStats {           */          int mUpdateVersion; -        SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) { +        @VisibleForTesting +        public SamplingTimer(Clocks clocks, TimeBase timeBase, Parcel in) {              super(clocks, 0, timeBase, in);              mCurrentReportedCount = in.readInt();              mUnpluggedReportedCount = in.readInt(); @@ -1259,7 +1261,8 @@ public class BatteryStatsImpl extends BatteryStats {              mTimeBaseRunning = timeBase.isRunning();          } -        SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) { +        @VisibleForTesting +        public SamplingTimer(Clocks clocks, TimeBase timeBase, boolean trackReportedValues) {              super(clocks, 0, timeBase);              mTrackingReportedValues = trackReportedValues;              mTimeBaseRunning = timeBase.isRunning(); diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index d8319022f431..b7e571871086 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -34,9 +34,11 @@ import java.io.File;  import java.io.FileInputStream;  import java.io.PrintWriter;  import java.io.StringWriter; +import java.text.SimpleDateFormat;  import java.util.ArrayList;  import java.util.Collections;  import java.util.Comparator; +import java.util.Date;  import java.util.StringTokenizer;  public class ProcessCpuTracker { @@ -147,6 +149,9 @@ public class ProcessCpuTracker {      private long mCurrentSampleRealTime;      private long mLastSampleRealTime; +    private long mCurrentSampleWallTime; +    private long mLastSampleWallTime; +      private long mBaseUserTime;      private long mBaseSystemTime;      private long mBaseIoWaitTime; @@ -305,6 +310,7 @@ public class ProcessCpuTracker {          final long nowUptime = SystemClock.uptimeMillis();          final long nowRealtime = SystemClock.elapsedRealtime(); +        final long nowWallTime = System.currentTimeMillis();          final long[] sysCpu = mSystemCpuData;          if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, @@ -367,6 +373,8 @@ public class ProcessCpuTracker {          mCurrentSampleTime = nowUptime;          mLastSampleRealTime = mCurrentSampleRealTime;          mCurrentSampleRealTime = nowRealtime; +        mLastSampleWallTime = mCurrentSampleWallTime; +        mCurrentSampleWallTime = nowWallTime;          final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();          try { @@ -710,6 +718,8 @@ public class ProcessCpuTracker {      }      final public String printCurrentState(long now) { +        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); +          buildWorkingProcs();          StringWriter sw = new StringWriter(); @@ -727,6 +737,11 @@ public class ProcessCpuTracker {              pw.print(mCurrentSampleTime-now);              pw.print("ms later");          } +        pw.print(" ("); +        pw.print(sdf.format(new Date(mLastSampleWallTime))); +        pw.print(" to "); +        pw.print(sdf.format(new Date(mCurrentSampleWallTime))); +        pw.print(")");          long sampleTime = mCurrentSampleTime - mLastSampleTime;          long sampleRealTime = mCurrentSampleRealTime - mLastSampleRealTime; diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java index b1598e7d16dd..b781fd47b1bd 100644 --- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java +++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java @@ -16,8 +16,6 @@  package com.android.internal.policy; -import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM; -  import android.graphics.Rect;  import android.graphics.drawable.ColorDrawable;  import android.graphics.drawable.Drawable; @@ -102,9 +100,6 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame          mOldSystemInsets.set(systemInsets);          mOldStableInsets.set(stableInsets);          mResizeMode = resizeMode; -        synchronized (this) { -            redrawLocked(initialBounds, fullscreen, mSystemInsets, mStableInsets); -        }          // Kick off our draw thread.          start(); @@ -160,7 +155,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame              mSystemInsets.set(systemInsets);              mStableInsets.set(stableInsets);              // Notify of a bounds change. -            pingRenderLocked(); +            pingRenderLocked(false /* drawImmediate */);          }      } @@ -172,7 +167,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame              if (mRenderer != null) {                  // Enforce a window redraw.                  mOldTargetRect.set(0, 0, 0, 0); -                pingRenderLocked(); +                pingRenderLocked(false /* drawImmediate */);              }          }      } @@ -197,7 +192,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame                  mRenderer = null;                  // Exit the renderer loop. -                pingRenderLocked(); +                pingRenderLocked(false /* drawImmediate */);              }          }      } @@ -208,9 +203,6 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame              Looper.prepare();              synchronized (this) {                  mChoreographer = Choreographer.getInstance(); - -                // Draw at least once. -                mChoreographer.postFrameCallback(this);              }              Looper.loop();          } finally { @@ -236,18 +228,22 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame                  Looper.myLooper().quit();                  return;              } -            mNewTargetRect.set(mTargetRect); -            if (!mNewTargetRect.equals(mOldTargetRect) -                    || mOldFullscreen != mFullscreen -                    || !mStableInsets.equals(mOldStableInsets) -                    || !mSystemInsets.equals(mOldSystemInsets) -                    || mReportNextDraw) { -                mOldFullscreen = mFullscreen; -                mOldTargetRect.set(mNewTargetRect); -                mOldSystemInsets.set(mSystemInsets); -                mOldStableInsets.set(mStableInsets); -                redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets); -            } +            doFrameUncheckedLocked(); +        } +    } + +    private void doFrameUncheckedLocked() { +        mNewTargetRect.set(mTargetRect); +        if (!mNewTargetRect.equals(mOldTargetRect) +                || mOldFullscreen != mFullscreen +                || !mStableInsets.equals(mOldStableInsets) +                || !mSystemInsets.equals(mOldSystemInsets) +                || mReportNextDraw) { +            mOldFullscreen = mFullscreen; +            mOldTargetRect.set(mNewTargetRect); +            mOldSystemInsets.set(mSystemInsets); +            mOldStableInsets.set(mStableInsets); +            redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);          }      } @@ -288,7 +284,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame          synchronized (this) {              mReportNextDraw = reportNextDraw;              mOldTargetRect.set(0, 0, 0, 0); -            pingRenderLocked(); +            pingRenderLocked(true /* drawImmediate */);          }      } @@ -403,10 +399,14 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame       * Sends a message to the renderer to wake up and perform the next action which can be       * either the next rendering or the self destruction if mRenderer is null.       * Note: This call must be synchronized. +     * +     * @param drawImmediate if we should draw immediately instead of scheduling a frame       */ -    private void pingRenderLocked() { -        if (mChoreographer != null) { +    private void pingRenderLocked(boolean drawImmediate) { +        if (mChoreographer != null && !drawImmediate) {              mChoreographer.postFrameCallback(this); +        } else { +            doFrameUncheckedLocked();          }      } diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java index 669e1efb9249..b8bc1618b3a3 100644 --- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java @@ -330,6 +330,14 @@ public class DividerSnapAlgorithm {          return snapTarget;      } +    public boolean isFirstSplitTargetAvailable() { +        return mFirstSplitTarget != mMiddleTarget; +    } + +    public boolean isLastSplitTargetAvailable() { +        return mLastSplitTarget != mMiddleTarget; +    } +      /**       * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left       * if {@param increment} is negative and moves right otherwise. diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 994bdebd880e..3d054225d234 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -41,7 +41,6 @@ interface IStatusBarService      void setImeWindowStatus(in IBinder token, int vis, int backDisposition,              boolean showImeSwitcher);      void expandSettingsPanel(String subPanel); -    void setCurrentUser(int newUserId);      // ---- Methods below are for use by the status bar policy services ----      // You need the STATUS_BAR_SERVICE permission @@ -63,48 +62,6 @@ interface IStatusBarService              in NotificationVisibility[] noLongerVisibleKeys);      void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);      void setSystemUiVisibility(int vis, int mask, String cause); -    void setWindowState(int window, int state); - -    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); -    void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); -    void toggleRecentApps(); -    void preloadRecentApps(); -    void cancelPreloadRecentApps(); - -    void toggleKeyboardShortcutsMenu(int deviceId); - -    /** -     * Notifies the status bar that an app transition is pending to delay applying some flags with -     * visual impact until {@link #appTransitionReady} is called. -     */ -    void appTransitionPending(); - -    /** -     * Notifies the status bar that a pending app transition has been cancelled. -     */ -    void appTransitionCancelled(); - -    /** -     * Notifies the status bar that an app transition is now being executed. -     * -     * @param statusBarAnimationsStartTime the desired start time for all visual animations in the -     *        status bar caused by this app transition in uptime millis -     * @param statusBarAnimationsDuration the duration for all visual animations in the status -     *        bar caused by this app transition in millis -     */ -    void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration); - -    void startAssist(in Bundle args); - -    /** -     * Request picture-in-picture. -     * -     * <p> -     * This is called when an user presses picture-in-picture key or equivalent. -     * TV device may start picture-in-picture from foreground activity if there's none. -     * Picture-in-picture overlay menu will be shown instead otherwise. -     */ -    void requestTvPictureInPicture();      void addTile(in ComponentName tile);      void remTile(in ComponentName tile); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index d8233a0ea34b..059013423f19 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -597,6 +597,13 @@ static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeO      ctrl->deferTransactionUntil(handle, frameNumber);  } +static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong nativeObject, +        jint scalingMode) { +    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + +    ctrl->setOverrideScalingMode(scalingMode); +} +  static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {      auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); @@ -676,6 +683,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {              (void*)nativeSetDisplayPowerMode },      {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",              (void*)nativeDeferTransactionUntil }, +    {"nativeSetOverrideScalingMode", "(JI)V", +            (void*)nativeSetOverrideScalingMode },      {"nativeGetHandle", "(J)Landroid/os/IBinder;",              (void*)nativeGetHandle }  }; diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java index e1b305f56b3b..a9fa4dd0d3a9 100644 --- a/core/tests/coretests/src/android/text/method/BackspaceTest.java +++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java @@ -420,10 +420,6 @@ public class BackspaceTest extends KeyListenerTestCase {          // Regional indicator symbol + ZERO WIDTH JOINER          state.setByString("U+1F1FA U+200D U+1F469 |");          backspace(state, 0); -        state.assertEquals("U+1F1FA U+200D |"); -        backspace(state, 0); -        state.assertEquals("U+1F1FA |"); -        backspace(state, 0);          state.assertEquals("|");          // Start with ZERO WIDTH JOINER + emoji modifier @@ -452,9 +448,7 @@ public class BackspaceTest extends KeyListenerTestCase {          // Emoji modifier + ZERO WIDTH JOINER          state.setByString("U+1F466 U+1F3FB U+200D U+1F469 |");          backspace(state, 0); -        state.assertEquals("U+1F466 U+1F3FB U+200D |"); -        backspace(state, 0); -        state.assertEquals("U+1F466 U+1F3FB |"); +        state.assertEquals("U+1F466 |");          backspace(state, 0);          state.assertEquals("|"); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java new file mode 100644 index 000000000000..51d41a40d71a --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.internal.os; + +import android.os.BatteryStats; +import android.os.Parcel; +import android.support.test.filters.SmallTest; + +import junit.framework.TestCase; + +public class BatteryStatsSamplingTimerTest extends TestCase { + +    @SmallTest +    public void testSampleTimerSummaryParceling() throws Exception { +        final MockClocks clocks = new MockClocks(); +        clocks.realtime = 0; +        clocks.uptime = 0; + +        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase(); +        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime()); + +        BatteryStatsImpl.SamplingTimer timer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, +                true); + +        // Start running on battery. +        timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime()); + +        // The first update on battery consumes the values as a way of starting cleanly. +        timer.addCurrentReportedTotalTime(10); +        timer.addCurrentReportedCount(1); + +        timer.addCurrentReportedTotalTime(10); +        timer.addCurrentReportedCount(1); + +        clocks.realtime = 20; +        clocks.uptime = 20; + +        assertEquals(10, timer.getTotalTimeLocked(clocks.elapsedRealtime(), +                BatteryStats.STATS_SINCE_CHARGED)); +        assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + +        // Grab a summary parcel while on battery. +        final Parcel onBatterySummaryParcel = Parcel.obtain(); +        timer.writeSummaryFromParcelLocked(onBatterySummaryParcel, clocks.elapsedRealtime() * 1000); +        onBatterySummaryParcel.setDataPosition(0); + +        // Stop running on battery. +        timeBase.setRunning(false, clocks.uptimeMillis(), clocks.elapsedRealtime()); + +        assertEquals(10, timer.getTotalTimeLocked(clocks.elapsedRealtime(), +                BatteryStats.STATS_SINCE_CHARGED)); +        assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + +        // Grab a summary parcel while not on battery. +        final Parcel offBatterySummaryParcel = Parcel.obtain(); +        timer.writeSummaryFromParcelLocked(offBatterySummaryParcel, +                clocks.elapsedRealtime() * 1000); +        offBatterySummaryParcel.setDataPosition(0); + +        // Read the on battery summary from the parcel. +        BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer( +                clocks, timeBase, true); +        unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel); + +        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); +        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + +        // Read the off battery summary from the parcel. +        unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase, true); +        unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel); + +        assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); +        assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); +    } +} diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java index 1c3cd3872d78..5fd822549ff8 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java @@ -16,20 +16,13 @@  package com.android.internal.os; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -  import android.os.BatteryStats;  import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; +import android.support.test.filters.SmallTest;  import junit.framework.Assert;  import junit.framework.TestCase; -import com.android.internal.os.BatteryStatsImpl; -  /**   * Provides test cases for android.os.BatteryStats.   */ diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java index 05aa53cacbc5..78bcbbc4ecb9 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java @@ -5,6 +5,7 @@ import org.junit.runners.Suite;  @RunWith(Suite.class)  @Suite.SuiteClasses({ +        BatteryStatsSamplingTimerTest.class,          BatteryStatsServTest.class,          BatteryStatsTimeBaseTest.class,          BatteryStatsTimerTest.class, diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java index ab92f158db84..3190d9e77c77 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java @@ -18,11 +18,10 @@ package com.android.internal.os;  import java.io.PrintWriter;  import java.io.StringWriter; -import java.util.ArrayList;  import android.os.BatteryStats;  import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; +import android.support.test.filters.SmallTest;  import android.util.Log;  import junit.framework.Assert; diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java index 3e17fcb8843d..98d0f7fdce5c 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java @@ -18,8 +18,7 @@ package com.android.internal.os;  import android.os.BatteryStats;  import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; +import android.support.test.filters.SmallTest;  import android.util.StringBuilderPrinter;  import junit.framework.Assert; @@ -148,7 +147,7 @@ public class BatteryStatsTimerTest extends TestCase {          timer.onTimeStarted(10, 20, 50);          Assert.assertEquals(50, timer.lastComputeRunTimeRealtime);          Assert.assertEquals(4, timer.getUnpluggedTime()); -        Assert.assertEquals(0, timer.getUnpluggedCount()); +        Assert.assertEquals(3000, timer.getUnpluggedCount());          // Test that stopping the timer updates mTotalTime and mCount          timer.nextComputeRunTime = 17; @@ -168,15 +167,16 @@ public class BatteryStatsTimerTest extends TestCase {          // Test write then read          TestTimer timer1 = new TestTimer(clocks, 0, timeBase);          timer1.setCount(1); -        timer1.setLoadedCount(2); -        timer1.setLastCount(3); -        timer1.setUnpluggedCount(4); +        timer1.setLoadedCount(3); +        timer1.setLastCount(4); +        timer1.setUnpluggedCount(5);          timer1.setTotalTime(9223372036854775807L);          timer1.setLoadedTime(9223372036854775806L);          timer1.setLastTime(9223372036854775805L);          timer1.setUnpluggedTime(9223372036854775804L);          timer1.setTimeBeforeMark(9223372036854775803L);          timer1.nextComputeRunTime = 201; +        timer1.nextComputeCurrentCount = 2;          Parcel parcel = Parcel.obtain();          Timer.writeTimerToParcel(parcel, timer1, 77); @@ -185,10 +185,10 @@ public class BatteryStatsTimerTest extends TestCase {          Assert.assertTrue("parcel null object", parcel.readInt() != 0);          TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel); -        Assert.assertEquals(1, timer2.getCount()); -        Assert.assertEquals(2, timer2.getLoadedCount()); +        Assert.assertEquals(2, timer2.getCount()); // from computeTotalCountLocked() +        Assert.assertEquals(3, timer2.getLoadedCount());          Assert.assertEquals(0, timer2.getLastCount()); // NOT saved -        Assert.assertEquals(4, timer2.getUnpluggedCount()); +        Assert.assertEquals(5, timer2.getUnpluggedCount());          Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked()          Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime());          Assert.assertEquals(0, timer2.getLastTime()); // NOT saved @@ -309,6 +309,7 @@ public class BatteryStatsTimerTest extends TestCase {          Parcel parcel = Parcel.obtain();          timer1.nextComputeRunTime = 9223372036854775800L; +        timer1.nextComputeCurrentCount = 1;          timer1.writeSummaryFromParcelLocked(parcel, 201);          Assert.assertEquals(40, timer1.lastComputeRunTimeRealtime); diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 35385ebcd57f..6762bea1ca35 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -310,6 +310,15 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {      @Override      public boolean setVisible(boolean visible, boolean restart) { +        if (mAnimatorSet.isInfinite() && mAnimatorSet.isStarted()) { +            if (visible) { +                // Resume the infinite animation when the drawable becomes visible again. +                mAnimatorSet.resume(); +            } else { +                // Pause the infinite animation once the drawable is no longer visible. +                mAnimatorSet.pause(); +            } +        }          mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);          return super.setVisible(visible, restart);      } @@ -815,6 +824,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {          void onDraw(Canvas canvas);          boolean isStarted();          boolean isRunning(); +        boolean isInfinite(); +        void pause(); +        void resume();      }      private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator { @@ -825,6 +837,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {          // Caching the listener in the case when listener operation is called before the mSet is          // setup by init().          private ArrayList<AnimatorListener> mListenerArray = null; +        private boolean mIsInfinite = false;          VectorDrawableAnimatorUI(@NonNull AnimatedVectorDrawable drawable) {              mDrawable = drawable; @@ -840,6 +853,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {              // Keep a deep copy of the set, such that set can be still be constantly representing              // the static content from XML file.              mSet = set.clone(); +            mIsInfinite = mSet.getTotalDuration() == Animator.DURATION_INFINITE;              // If there are listeners added before calling init(), now they should be setup.              if (mListenerArray != null && !mListenerArray.isEmpty()) { @@ -934,6 +948,27 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {              return mSet != null && mSet.isRunning();          } +        @Override +        public boolean isInfinite() { +            return mIsInfinite; +        } + +        @Override +        public void pause() { +            if (mSet == null) { +                return; +            } +            mSet.pause(); +        } + +        @Override +        public void resume() { +            if (mSet == null) { +                return; +            } +            mSet.resume(); +        } +          private void invalidateOwningView() {              mDrawable.invalidateSelf();          } @@ -956,6 +991,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {          private boolean mStarted = false;          private boolean mInitialized = false;          private boolean mIsReversible = false; +        private boolean mIsInfinite = false;          // This needs to be set before parsing starts.          private boolean mShouldIgnoreInvalidAnim;          // TODO: Consider using NativeAllocationRegistery to track native allocation @@ -983,6 +1019,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {              mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation();              parseAnimatorSet(set, 0);              mInitialized = true; +            mIsInfinite = set.getTotalDuration() == Animator.DURATION_INFINITE;              // Check reversible.              mIsReversible = true; @@ -1408,6 +1445,21 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {              }          } +        @Override +        public boolean isInfinite() { +            return mIsInfinite; +        } + +        @Override +        public void pause() { +            // TODO: Implement pause for Animator On RT. +        } + +        @Override +        public void resume() { +            // TODO: Implement resume for Animator On RT. +        } +          private void onAnimationEnd(int listenerId) {              if (listenerId != mLastListenerId) {                  return; diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml index be21b55c4066..e67cc8a06da2 100644 --- a/packages/DocumentsUI/res/values/strings.xml +++ b/packages/DocumentsUI/res/values/strings.xml @@ -247,4 +247,9 @@          <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> item?</item>          <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> items?</item>      </plurals> +    <!-- Snackbar shown to users who wanted to select more than 1000 items (files or directories). --> +    <string name="too_many_selected">Sorry, you can only select up to 1000 items at a time</string> +    <!-- Snackbar shown to users who wanted to select all, but there were too many items (files or directories). +         Only the first 1000 items are selected in such case. --> +    <string name="too_many_in_select_all">Could only select 1000 items</string>  </resources> diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java index babde992a90b..c78face9730a 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java @@ -17,6 +17,7 @@  package com.android.documentsui;  import static com.android.documentsui.Shared.DEBUG; +import static com.android.documentsui.Shared.MAX_DOCS_IN_INTENT;  import static com.android.documentsui.model.DocumentInfo.getCursorString;  import android.content.ClipData; @@ -46,7 +47,6 @@ import java.util.List;  final class QuickViewIntentBuilder {      private static final String TAG = "QuickViewIntentBuilder"; -    private static final int MAX_CLIP_ITEMS = 1000;      private final DocumentInfo mDocument;      private final Model mModel; @@ -165,11 +165,11 @@ final class QuickViewIntentBuilder {          int firstSibling;          int lastSibling;          if (documentLocation < uris.size() / 2) { -            firstSibling = Math.max(0, documentLocation - MAX_CLIP_ITEMS / 2); -            lastSibling = Math.min(uris.size() - 1, firstSibling + MAX_CLIP_ITEMS - 1); +            firstSibling = Math.max(0, documentLocation - MAX_DOCS_IN_INTENT / 2); +            lastSibling = Math.min(uris.size() - 1, firstSibling + MAX_DOCS_IN_INTENT - 1);          } else { -            lastSibling = Math.min(uris.size() - 1, documentLocation + MAX_CLIP_ITEMS / 2); -            firstSibling = Math.max(0, lastSibling - MAX_CLIP_ITEMS + 1); +            lastSibling = Math.min(uris.size() - 1, documentLocation + MAX_DOCS_IN_INTENT / 2); +            firstSibling = Math.max(0, lastSibling - MAX_DOCS_IN_INTENT + 1);          }          if (DEBUG) Log.d(TAG, "Copmuted siblings from index: " + firstSibling diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java index 1ba836a7fa4a..07c3cdbcbec0 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java @@ -104,6 +104,11 @@ public final class Shared {       */      public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark"; +    /** +     * Maximum number of items in a Binder transaction packet. +     */ +    public static final int MAX_DOCS_IN_INTENT = 1000; +      private static final Collator sCollator;      static { diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 8c073c9cc616..297fbc784acd 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -17,6 +17,7 @@  package com.android.documentsui.dirlist;  import static com.android.documentsui.Shared.DEBUG; +import static com.android.documentsui.Shared.MAX_DOCS_IN_INTENT;  import static com.android.documentsui.State.MODE_GRID;  import static com.android.documentsui.State.MODE_LIST;  import static com.android.documentsui.State.SORT_ORDER_UNKNOWN; @@ -108,9 +109,11 @@ import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.util.ArrayList;  import java.util.Collections; +import java.util.HashSet;  import java.util.Iterator;  import java.util.List;  import java.util.Objects; +import java.util.Set;  /**   * Display the documents inside a single directory. @@ -475,8 +478,18 @@ public class DirectoryFragment extends Fragment                  final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);                  final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); +                if (!mTuner.canSelectType(docMimeType, docFlags)) { +                    return false; +                } -                return mTuner.canSelectType(docMimeType, docFlags); +                if (mSelected.size() >= MAX_DOCS_IN_INTENT) { +                    Snackbars.makeSnackbar( +                            getActivity(), +                            R.string.too_many_selected, +                            Snackbar.LENGTH_SHORT) +                            .show(); +                    return false; +                }              }              return true;          } @@ -1108,9 +1121,17 @@ public class DirectoryFragment extends Fragment      public void selectAllFiles() {          Metrics.logUserAction(getContext(), Metrics.USER_ACTION_SELECT_ALL); -        // Exclude disabled files -        List<String> enabled = new ArrayList<String>(); -        for (String id : mAdapter.getModelIds()) { +        // Exclude disabled files. +        Set<String> enabled = new HashSet<String>(); +        List<String> modelIds = mAdapter.getModelIds(); + +        // Get the current selection. +        String[] alreadySelected = mSelectionManager.getSelection().getAll(); +        for (String id : alreadySelected) { +           enabled.add(id); +        } + +        for (String id : modelIds) {              Cursor cursor = getModel().getItem(id);              if (cursor == null) {                  Log.w(TAG, "Skipping selection. Can't obtain cursor for modeId: " + id); @@ -1118,7 +1139,15 @@ public class DirectoryFragment extends Fragment              }              String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);              int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); -            if (isDocumentEnabled(docMimeType, docFlags)) { +            if (mTuner.canSelectType(docMimeType, docFlags)) { +                if (enabled.size() >= MAX_DOCS_IN_INTENT) { +                    Snackbars.makeSnackbar( +                        getActivity(), +                        R.string.too_many_in_select_all, +                        Snackbar.LENGTH_SHORT) +                        .show(); +                    break; +                }                  enabled.add(id);              }          } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java index e3eae33ccc09..ecdbe63b75dd 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java @@ -154,7 +154,8 @@ public abstract class FragmentTuner {              MenuItem rename = menu.findItem(R.id.menu_rename);              MenuItem selectAll = menu.findItem(R.id.menu_select_all); -            open.setVisible(true); +            open.setVisible(mState.action == ACTION_GET_CONTENT || +                    mState.action == ACTION_OPEN);              share.setVisible(false);              delete.setVisible(false);              rename.setVisible(false); diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java index 35d8988244f6..8852985da5d5 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java @@ -154,6 +154,10 @@ public final class MultiSelectManager {                          // Update the selection to remove any disappeared IDs.                          mSelection.cancelProvisionalSelection();                          mSelection.intersect(mModelIds); + +                        if (mBandManager != null && mBandManager.isActive()) { +                            mBandManager.endBandSelect(); +                        }                      }                      @Override @@ -940,6 +944,10 @@ public final class MultiSelectManager {           * Layout items are excluded from the GridModel.           */          boolean isLayoutItem(int adapterPosition); +        /** +         * Items may be in the adapter, but without an attached view. +         */ +        boolean hasView(int adapterPosition);      }      /** Recycler view facade implementation backed by good ol' RecyclerView. */ @@ -1061,6 +1069,11 @@ public final class MultiSelectManager {                      return true;              }          } + +        @Override +        public boolean hasView(int pos) { +            return mView.findViewHolderForAdapterPosition(pos) != null; +        }      }      public interface Callback { @@ -1473,10 +1486,14 @@ public final class MultiSelectManager {           *     y-value.           */          void startSelection(Point relativeOrigin) { +            recordVisibleChildren(); +            if (isEmpty()) { +                // The selection band logic works only if there is at least one visible child. +                return; +            } +              mIsActive = true;              mPointer = mHelper.createAbsolutePoint(relativeOrigin); - -            recordVisibleChildren();              mRelativeOrigin = new RelativePoint(mPointer);              mRelativePointer = new RelativePoint(mPointer);              computeCurrentSelection(); @@ -1530,7 +1547,11 @@ public final class MultiSelectManager {          private void recordVisibleChildren() {              for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {                  int adapterPosition = mHelper.getAdapterPositionAt(i); -                if (!mHelper.isLayoutItem(adapterPosition) && +                // Sometimes the view is not attached, as we notify the multi selection manager +                // synchronously, while views are attached asynchronously. As a result items which +                // are in the adapter may not actually have a corresponding view (yet). +                if (mHelper.hasView(adapterPosition) && +                        !mHelper.isLayoutItem(adapterPosition) &&                          !mKnownPositions.get(adapterPosition)) {                      mKnownPositions.put(adapterPosition, true);                      recordItemData(mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition); @@ -1539,6 +1560,13 @@ public final class MultiSelectManager {          }          /** +         * Checks if there are any recorded children. +         */ +        private boolean isEmpty() { +            return mColumnBounds.size() == 0 || mRowBounds.size() == 0; +        } + +        /**           * Updates the limits lists and column map with the given item metadata.           * @param absoluteChildRect The absolute rectangle for the child view being processed.           * @param adapterPosition The position of the child view being processed. diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java index cc119fec8267..e401de160708 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java @@ -448,6 +448,11 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase {              return false;          } +        @Override +        public boolean hasView(int adapterPosition) { +            return true; +        } +          public static final class Item {              public String name;              public Rect rect; diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java index 56e54a61cfc0..f56476978a4e 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java @@ -100,4 +100,9 @@ public class TestSelectionEnvironment implements SelectionEnvironment {      public boolean isLayoutItem(int adapterPosition) {          return false;      } + +    @Override +    public boolean hasView(int adapterPosition) { +        return true; +    }  } diff --git a/packages/SettingsLib/res/layout/drawer_category.xml b/packages/SettingsLib/res/layout/drawer_category.xml index b7b50d023e09..582821bdf6bb 100644 --- a/packages/SettingsLib/res/layout/drawer_category.xml +++ b/packages/SettingsLib/res/layout/drawer_category.xml @@ -28,7 +28,8 @@      <TextView          android:id="@android:id/title"          android:layout_width="match_parent" -        android:layout_height="48dp" +        android:layout_height="wrap_content" +        android:minHeight="48dp"          android:paddingTop="16dp"          android:paddingBottom="16dp"          android:paddingStart="16dp" diff --git a/packages/SettingsLib/res/layout/drawer_item.xml b/packages/SettingsLib/res/layout/drawer_item.xml index 4b53049fe9b1..e1f1ae5ef706 100644 --- a/packages/SettingsLib/res/layout/drawer_item.xml +++ b/packages/SettingsLib/res/layout/drawer_item.xml @@ -17,7 +17,8 @@      xmlns:android="http://schemas.android.com/apk/res/android"      android:id="@+id/tile_item"      android:layout_width="match_parent" -    android:layout_height="48dp" +    android:layout_height="wrap_content" +    android:minHeight="48dp"      android:orientation="horizontal" >      <ImageView diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index b557dc4d8671..4e9b59fe6b18 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -111,6 +111,8 @@      <uses-permission android:name="android.permission.VIBRATE" />      <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />      <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" /> +    <!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) --> +    <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />      <application android:label="@string/app_label"                   android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 346ae201cdb6..ec3999808c8c 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -62,6 +62,7 @@ import android.content.Intent;  import android.content.res.Configuration;  import android.net.Uri;  import android.os.AsyncTask; +import android.os.Bundle;  import android.os.Handler;  import android.os.HandlerThread;  import android.os.IBinder; @@ -204,6 +205,8 @@ public class BugreportProgressService extends Service {       */      private boolean mTakingScreenshot; +    private static final Bundle sNotificationBundle = new Bundle(); +      @Override      public void onCreate() {          mContext = getApplicationContext(); @@ -979,7 +982,13 @@ public class BugreportProgressService extends Service {      }      private static Notification.Builder newBaseNotification(Context context) { +        if (sNotificationBundle.isEmpty()) { +            // Rename notifcations from "Shell" to "Android System" +            sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, +                    context.getString(com.android.internal.R.string.android_system_label)); +        }          return new Notification.Builder(context) +                .addExtras(sNotificationBundle)                  .setCategory(Notification.CATEGORY_SYSTEM)                  .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)                  .setLocalOnly(true) diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml index 55d7fab3898e..68129cee28cc 100644 --- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml +++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml @@ -45,7 +45,7 @@              android:layout_gravity="end"              android:minWidth="88dp"              android:textAppearance="@style/TextAppearance.QS.DetailButton" -            android:textColor="#4DFFFFFF" +            android:textColor="#64FFFFFF"              android:focusable="true"              android:text="@string/qs_edit" /> diff --git a/packages/SystemUI/res/values-sw410dp/config.xml b/packages/SystemUI/res/values-sw410dp/config.xml index 08b2f8876470..049a5357c6da 100644 --- a/packages/SystemUI/res/values-sw410dp/config.xml +++ b/packages/SystemUI/res/values-sw410dp/config.xml @@ -21,4 +21,6 @@       for different hardware and product builds. -->  <resources>      <integer name="quick_settings_num_rows">2</integer> + +    <bool name="quick_settings_show_date">true</bool>  </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index c54db378bf67..ef84c76c4c5c 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -268,5 +268,7 @@      <!-- Nav bar button default ordering/layout -->      <string name="config_navBarLayout" translatable="false">space,back;home;recent,menu_ime</string> +    <bool name="quick_settings_show_date">false</bool> +  </resources> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 9697ea6f3788..94d79f27e67f 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -63,9 +63,10 @@      <item type="id" name="is_clicked_heads_up_tag" />      <!-- Accessibility actions for the docked stack divider --> -    <item type="id" name="action_move_left" /> -    <item type="id" name="action_move_right" /> -    <item type="id" name="action_move_up" /> -    <item type="id" name="action_move_down" /> +    <item type="id" name="action_move_tl_full" /> +    <item type="id" name="action_move_tl_70" /> +    <item type="id" name="action_move_tl_50" /> +    <item type="id" name="action_move_tl_30" /> +    <item type="id" name="action_move_rb_full" />  </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index a03aa28c47c5..8e3ea4c946e0 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1580,17 +1580,27 @@      <!-- Accessibility label for the divider that separates the windows in split-screen mode [CHAR LIMIT=NONE] -->      <string name="accessibility_divider">Split-screen divider</string> -    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] --> -    <string name="accessibility_action_divider_move_down">Move down</string> - -    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] --> -    <string name="accessibility_action_divider_move_up">Move up</string> - -    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] --> -    <string name="accessibility_action_divider_move_left">Move left</string> - -    <!-- Accessibility action for moving down the docked stack divider [CHAR LIMIT=NONE] --> -    <string name="accessibility_action_divider_move_right">Move right</string> +    <!-- Accessibility action for moving docked stack divider to make the left screen full screen [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_left_full">Left full screen</string> +    <!-- Accessibility action for moving docked stack divider to make the left screen 70% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_left_70">Left 70%</string> +    <!-- Accessibility action for moving docked stack divider to make the left screen 50% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_left_50">Left 50%</string> +    <!-- Accessibility action for moving docked stack divider to make the left screen 30% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_left_30">Left 30%</string> +    <!-- Accessibility action for moving docked stack divider to make the right screen full screen [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_right_full">Right full screen</string> + +    <!-- Accessibility action for moving docked stack divider to make the top screen full screen [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_top_full">Top full screen</string> +    <!-- Accessibility action for moving docked stack divider to make the top screen 70% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_top_70">Top 70%</string> +    <!-- Accessibility action for moving docked stack divider to make the top screen 50% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_top_50">Top 50%</string> +    <!-- Accessibility action for moving docked stack divider to make the top screen 30% [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_top_30">Top 30%</string> +    <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] --> +    <string name="accessibility_action_divider_bottom_full">Bottom full screen</string>      <!-- Accessibility description of a QS tile while editing positions [CHAR LIMIT=NONE] -->      <string name="accessibility_qs_edit_tile_label">Position <xliff:g id="position" example="2">%1$d</xliff:g>, <xliff:g id="tile_name" example="Wi-Fi">%2$s</xliff:g>. Double tap to edit.</string> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index d12ab293ab3e..cecbfcb236ba 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -317,8 +317,8 @@ public class ExpandHelper implements Gefingerpoken {                      mResizedView = null;                      mWatchingForPull = false;                  } -                mInitialTouchY = ev.getY(); -                mInitialTouchX = ev.getX(); +                mInitialTouchY = ev.getRawY(); +                mInitialTouchX = ev.getRawX();                  break;              case MotionEvent.ACTION_CANCEL: @@ -412,8 +412,8 @@ public class ExpandHelper implements Gefingerpoken {                  mWatchingForPull = mScrollAdapter != null &&                          isInside(mScrollAdapter.getHostView(), x, y);                  mResizedView = findView(x, y); -                mInitialTouchX = ev.getX(); -                mInitialTouchY = ev.getY(); +                mInitialTouchX = ev.getRawX(); +                mInitialTouchY = ev.getRawY();                  break;              case MotionEvent.ACTION_MOVE: {                  if (mWatchingForPull) { diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 130628442dfb..c72f5d2f18cd 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -29,6 +29,7 @@ import android.graphics.Rect;  import android.graphics.RectF;  import android.graphics.Region.Op;  import android.opengl.GLUtils; +import android.os.AsyncTask;  import android.os.SystemProperties;  import android.renderscript.Matrix4f;  import android.service.wallpaper.WallpaperService; @@ -155,6 +156,8 @@ public class ImageWallpaper extends WallpaperService {          private int mLastRequestedWidth = -1;          private int mLastRequestedHeight = -1; +        private AsyncTask<Void, Void, Bitmap> mLoader; +        private boolean mNeedsDrawAfterLoadingWallpaper;          public DrawableEngine() {              super(); @@ -184,10 +187,9 @@ public class ImageWallpaper extends WallpaperService {              super.onCreate(surfaceHolder);              mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay(); - -            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo()); -              setOffsetNotificationsEnabled(false); + +            updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo(), false /* forDraw */);          }          @Override @@ -197,17 +199,19 @@ public class ImageWallpaper extends WallpaperService {              mWallpaperManager.forgetLoadedWallpaper();          } -        void updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo) { +        boolean updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo, +                boolean forDraw) { +            boolean hasWallpaper = true; +              // Load background image dimensions, if we haven't saved them yet              if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {                  // Need to load the image to get dimensions                  mWallpaperManager.forgetLoadedWallpaper(); -                updateWallpaperLocked(); -                if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) { -                    // Default to the display size if we can't find the dimensions -                    mBackgroundWidth = displayInfo.logicalWidth; -                    mBackgroundHeight = displayInfo.logicalHeight; +                loadWallpaper(forDraw); +                if (DEBUG) { +                    Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");                  } +                hasWallpaper = false;              }              // Force the wallpaper to cover the screen in both dimensions @@ -224,6 +228,7 @@ public class ImageWallpaper extends WallpaperService {              } else {                  surfaceHolder.setSizeFromLayout();              } +            return hasWallpaper;          }          @Override @@ -299,6 +304,7 @@ public class ImageWallpaper extends WallpaperService {              }              super.onSurfaceRedrawNeeded(holder); +            mLastSurfaceHeight = mLastSurfaceWidth = -1;              drawFrame();          } @@ -317,7 +323,9 @@ public class ImageWallpaper extends WallpaperService {                  // should change                  if (newRotation != mLastRotation) {                      // Update surface size (if necessary) -                    updateSurfaceSize(getSurfaceHolder(), displayInfo); +                    if (!updateSurfaceSize(getSurfaceHolder(), displayInfo, true /* forDraw */)) { +                        return; // had to reload wallpaper, will retry later +                    }                      mRotationAtLastSurfaceSizeUpdate = newRotation;                      mDisplayWidthAtLastSurfaceSizeUpdate = displayInfo.logicalWidth;                      mDisplayHeightAtLastSurfaceSizeUpdate = displayInfo.logicalHeight; @@ -339,8 +347,8 @@ public class ImageWallpaper extends WallpaperService {                  }                  mLastRotation = newRotation; -                // Load bitmap if it is not yet loaded or if it was loaded at a different size -                if (mBackground == null || surfaceDimensionsChanged) { +                // Load bitmap if it is not yet loaded +                if (mBackground == null) {                      if (DEBUG) {                          Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +                                  mBackground + ", " + @@ -349,20 +357,11 @@ public class ImageWallpaper extends WallpaperService {                                  dw + ", " + dh);                      }                      mWallpaperManager.forgetLoadedWallpaper(); -                    updateWallpaperLocked(); -                    if (mBackground == null) { -                        if (DEBUG) { -                            Log.d(TAG, "Unable to load bitmap"); -                        } -                        return; -                    } +                    loadWallpaper(true /* needDraw */);                      if (DEBUG) { -                        if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) { -                            Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " + -                                    dw + ", " + dh + ", " + mBackground.getWidth() + ", " + -                                    mBackground.getHeight()); -                        } +                        Log.d(TAG, "Reloading, resuming draw later");                      } +                    return;                  }                  // Center the scaled image @@ -422,36 +421,77 @@ public class ImageWallpaper extends WallpaperService {              }          } -        private void updateWallpaperLocked() { -            Throwable exception = null; -            try { -                mBackground = null; -                mBackgroundWidth = -1; -                mBackgroundHeight = -1; -                mBackground = mWallpaperManager.getBitmap(); -                mBackgroundWidth = mBackground.getWidth(); -                mBackgroundHeight = mBackground.getHeight(); -            } catch (RuntimeException e) { -                exception = e; -            } catch (OutOfMemoryError e) { -                exception = e; +        /** +         * Loads the wallpaper on background thread and schedules updating the surface frame, +         * and if {@param needsDraw} is set also draws a frame. +         * +         * If loading is already in-flight, subsequent loads are ignored (but needDraw is or-ed to +         * the active request). +         */ +        private void loadWallpaper(boolean needsDraw) { +            mNeedsDrawAfterLoadingWallpaper |= needsDraw; +            if (mLoader != null) { +                if (DEBUG) { +                    Log.d(TAG, "Skipping loadWallpaper, already in flight "); +                } +                return;              } +            mLoader = new AsyncTask<Void, Void, Bitmap>() { +                @Override +                protected Bitmap doInBackground(Void... params) { +                    Throwable exception; +                    try { +                        return mWallpaperManager.getBitmap(); +                    } catch (RuntimeException | OutOfMemoryError e) { +                        exception = e; +                    } -            if (exception != null) { -                mBackground = null; -                mBackgroundWidth = -1; -                mBackgroundHeight = -1; -                // Note that if we do fail at this, and the default wallpaper can't -                // be loaded, we will go into a cycle.  Don't do a build where the -                // default wallpaper can't be loaded. -                Log.w(TAG, "Unable to load wallpaper!", exception); -                try { -                    mWallpaperManager.clear(); -                } catch (IOException ex) { -                    // now we're really screwed. -                    Log.w(TAG, "Unable reset to default wallpaper!", ex); +                    if (exception != null) { +                        // Note that if we do fail at this, and the default wallpaper can't +                        // be loaded, we will go into a cycle.  Don't do a build where the +                        // default wallpaper can't be loaded. +                        Log.w(TAG, "Unable to load wallpaper!", exception); +                        try { +                            mWallpaperManager.clear(); +                        } catch (IOException ex) { +                            // now we're really screwed. +                            Log.w(TAG, "Unable reset to default wallpaper!", ex); +                        } + +                        try { +                            return mWallpaperManager.getBitmap(); +                        } catch (RuntimeException | OutOfMemoryError e) { +                            Log.w(TAG, "Unable to load default wallpaper!", e); +                        } +                    } +                    return null;                  } -            } + +                @Override +                protected void onPostExecute(Bitmap b) { +                    mBackground = null; +                    mBackgroundWidth = -1; +                    mBackgroundHeight = -1; + +                    if (b != null) { +                        mBackground = b; +                        mBackgroundWidth = mBackground.getWidth(); +                        mBackgroundHeight = mBackground.getHeight(); +                    } + +                    if (DEBUG) { +                        Log.d(TAG, "Wallpaper loaded: " + mBackground); +                    } +                    updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(), +                            false /* forDraw */); +                    if (mNeedsDrawAfterLoadingWallpaper) { +                        drawFrame(); +                    } + +                    mLoader = null; +                    mNeedsDrawAfterLoadingWallpaper = false; +                } +            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);          }          @Override diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java index eaafafac3f87..94b2fdbf5ff8 100644 --- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java @@ -21,9 +21,9 @@ import android.view.Display;  import android.view.View;  public interface RecentsComponent { -    void showRecents(boolean triggeredFromAltTab, boolean fromHome, View statusBarView); +    void showRecents(boolean triggeredFromAltTab, boolean fromHome);      void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); -    void toggleRecents(Display display, int layoutDirection, View statusBarView); +    void toggleRecents(Display display);      void preloadRecents();      void cancelPreloadingRecents();      void showNextAffiliatedTask(); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java index f619bfbcd047..c8a2e1758ad1 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java @@ -16,11 +16,9 @@  package com.android.systemui; -import android.app.ActivityManager;  import android.app.Service;  import android.content.Intent;  import android.os.IBinder; -import android.os.Process;  import java.io.FileDescriptor;  import java.io.PrintWriter; @@ -43,15 +41,19 @@ public class SystemUISecondaryUserService extends Service {          SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();          if (args == null || args.length == 0) {              for (SystemUI ui: services) { -                pw.println("dumping service: " + ui.getClass().getName()); -                ui.dump(fd, pw, args); +                if (ui != null) { +                    pw.println("dumping service: " + ui.getClass().getName()); +                    ui.dump(fd, pw, args); +                }              }          } else {              String svc = args[0];              for (SystemUI ui: services) { -                String name = ui.getClass().getName(); -                if (name.endsWith(svc)) { -                    ui.dump(fd, pw, args); +                if (ui != null) { +                    String name = ui.getClass().getName(); +                    if (name.endsWith(svc)) { +                        ui.dump(fd, pw, args); +                    }                  }              }          } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java index 0798590b68f5..1ac59925a70a 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java @@ -27,6 +27,7 @@ import android.os.PowerManager;  import android.os.UserHandle;  import android.provider.Settings;  import android.view.MotionEvent; +import android.view.accessibility.AccessibilityManager;  import com.android.systemui.analytics.DataCollector;  import com.android.systemui.statusbar.StatusBarState; @@ -60,6 +61,7 @@ public class FalsingManager implements SensorEventListener {      private final SensorManager mSensorManager;      private final DataCollector mDataCollector;      private final HumanInteractionClassifier mHumanInteractionClassifier; +    private final AccessibilityManager mAccessibilityManager;      private static FalsingManager sInstance = null; @@ -78,7 +80,8 @@ public class FalsingManager implements SensorEventListener {      private FalsingManager(Context context) {          mContext = context; -        mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); +        mSensorManager = mContext.getSystemService(SensorManager.class); +        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);          mDataCollector = DataCollector.getInstance(mContext);          mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);          mScreenOn = context.getSystemService(PowerManager.class).isInteractive(); @@ -177,6 +180,11 @@ public class FalsingManager implements SensorEventListener {                          .toString());              }          } +        if (mAccessibilityManager.isTouchExplorationEnabled()) { +            // Touch exploration triggers false positives in the classifier and +            // already sufficiently prevents false unlocks. +            return false; +        }          return mHumanInteractionClassifier.isFalseTouch();      } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 1149c5961743..74f1b804999a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -70,6 +70,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {      private QSCustomizer mCustomizePanel;      private Record mDetailRecord; +    private boolean mTriggeredExpand;      public QSPanel(Context context) {          this(context, null); @@ -384,8 +385,16 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {      }      protected void handleShowDetail(Record r, boolean show) { -        if (show && !mExpanded) { -            mHost.animateExpandQS(); +        if (show) { +            if (!mExpanded) { +                mTriggeredExpand = true; +                mHost.animateToggleQSExpansion(); +            } else { +                mTriggeredExpand = false; +            } +        } else if (mTriggeredExpand) { +            mHost.animateToggleQSExpansion(); +            mTriggeredExpand = false;          }          if (r instanceof TileRecord) {              handleShowDetailTile((TileRecord) r, show); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index 3e32905d64cd..76925981c8f5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -389,7 +389,7 @@ public abstract class QSTile<TState extends State> implements Listenable {          void startRunnableDismissingKeyguard(Runnable runnable);          void warn(String message, Throwable t);          void collapsePanels(); -        void animateExpandQS(); +        void animateToggleQSExpansion();          void openPanels();          Looper getLooper();          Context getContext(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl index 7ce9384258fe..940366444e63 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl @@ -27,9 +27,9 @@ oneway interface IRecentsNonSystemUserCallbacks {      void preloadRecents();      void cancelPreloadingRecents();      void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate, -            boolean reloadTasks, boolean fromHome); +            boolean reloadTasks, boolean fromHome, int recentsGrowTarget);      void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); -    void toggleRecents(); +    void toggleRecents(int recentsGrowTarget);      void onConfigurationChanged();      void dockTopTask(int topTaskId, int dragMode, int stackCreateMode,              in Rect initialBounds); diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index bb709c5ca9c0..630cb6655a19 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -37,9 +37,7 @@ import android.os.UserHandle;  import android.provider.Settings;  import android.util.EventLog;  import android.util.Log; -import android.util.MutableBoolean;  import android.view.Display; -import android.view.View;  import android.widget.Toast;  import com.android.internal.logging.MetricsLogger; @@ -59,6 +57,7 @@ import com.android.systemui.recents.events.ui.RecentsDrawnEvent;  import com.android.systemui.recents.misc.SystemServicesProxy;  import com.android.systemui.recents.model.RecentsTaskLoader;  import com.android.systemui.recents.tv.RecentsTvImpl; +import com.android.systemui.stackdivider.Divider;  import java.util.ArrayList; @@ -75,6 +74,7 @@ public class Recents extends SystemUI      public final static int EVENT_BUS_PRIORITY = 1;      public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000; +    public final static int RECENTS_GROW_TARGET_INVALID = -1;      // Purely for experimentation      private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg"; @@ -238,7 +238,7 @@ public class Recents extends SystemUI       * Shows the Recents.       */      @Override -    public void showRecents(boolean triggeredFromAltTab, boolean fromHome, View statusBarView) { +    public void showRecents(boolean triggeredFromAltTab, boolean fromHome) {          // Ensure the device has been provisioned before allowing the user to interact with          // recents          if (!isUserSetup()) { @@ -249,10 +249,12 @@ public class Recents extends SystemUI              return;          } +        int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents(); +          int currentUser = sSystemServicesProxy.getCurrentUser();          if (sSystemServicesProxy.isSystemUser(currentUser)) {              mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */, -                    true /* animate */, false /* reloadTasks */, fromHome); +                    true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget);          } else {              if (mSystemToUserCallbacks != null) {                  IRecentsNonSystemUserCallbacks callbacks = @@ -260,7 +262,8 @@ public class Recents extends SystemUI                  if (callbacks != null) {                      try {                          callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */, -                                true /* animate */, false /* reloadTasks */, fromHome); +                                true /* animate */, false /* reloadTasks */, fromHome, +                                recentsGrowTarget);                      } catch (RemoteException e) {                          Log.e(TAG, "Callback failed", e);                      } @@ -310,7 +313,7 @@ public class Recents extends SystemUI       * Toggles the Recents activity.       */      @Override -    public void toggleRecents(Display display, int layoutDirection, View statusBarView) { +    public void toggleRecents(Display display) {          // Ensure the device has been provisioned before allowing the user to interact with          // recents          if (!isUserSetup()) { @@ -321,16 +324,18 @@ public class Recents extends SystemUI              return;          } +        int growTarget = getComponent(Divider.class).getView().growsRecents(); +          int currentUser = sSystemServicesProxy.getCurrentUser();          if (sSystemServicesProxy.isSystemUser(currentUser)) { -            mImpl.toggleRecents(); +            mImpl.toggleRecents(growTarget);          } else {              if (mSystemToUserCallbacks != null) {                  IRecentsNonSystemUserCallbacks callbacks =                          mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);                  if (callbacks != null) {                      try { -                        callbacks.toggleRecents(); +                        callbacks.toggleRecents(growTarget);                      } catch (RemoteException e) {                          Log.e(TAG, "Callback failed", e);                      } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 3ecada961a24..f961390043eb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -38,8 +38,10 @@ import android.util.MutableBoolean;  import android.view.AppTransitionAnimationSpec;  import android.view.LayoutInflater;  import android.view.ViewConfiguration; +import android.view.WindowManager;  import com.android.internal.logging.MetricsLogger; +import com.android.internal.policy.DockedDividerUtils;  import com.android.systemui.R;  import com.android.systemui.SystemUIApplication;  import com.android.systemui.recents.events.EventBus; @@ -68,6 +70,7 @@ import com.android.systemui.recents.views.TaskStackView;  import com.android.systemui.recents.views.TaskStackViewScroller;  import com.android.systemui.recents.views.TaskViewHeader;  import com.android.systemui.recents.views.TaskViewTransform; +import com.android.systemui.stackdivider.DividerView;  import com.android.systemui.statusbar.BaseStatusBar;  import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;  import com.android.systemui.statusbar.phone.PhoneStatusBar; @@ -156,7 +159,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener              // When this fires, then the user has not released alt-tab for at least              // FAST_ALT_TAB_DELAY_MS milliseconds              showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */, -                    false /* reloadTasks */, false /* fromHome */); +                    false /* reloadTasks */, false /* fromHome */, +                    DividerView.INVALID_RECENTS_GROW_TARGET);          }      }); @@ -230,7 +234,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener      }      public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, -            boolean animate, boolean launchedWhileDockingTask, boolean fromHome) { +            boolean animate, boolean launchedWhileDockingTask, boolean fromHome, +            int growTarget) {          mTriggeredFromAltTab = triggeredFromAltTab;          mDraggingInRecents = draggingInRecents;          mLaunchedWhileDocking = launchedWhileDockingTask; @@ -260,7 +265,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener              ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();              MutableBoolean isTopTaskHome = new MutableBoolean(true);              if (topTask == null || !ssp.isRecentsTopMost(topTask, isTopTaskHome)) { -                startRecentsActivity(topTask, isTopTaskHome.value || fromHome, animate); +                startRecentsActivity(topTask, isTopTaskHome.value || fromHome, animate, growTarget);              }          } catch (ActivityNotFoundException e) {              Log.e(TAG, "Failed to launch RecentsActivity", e); @@ -284,7 +289,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener                  triggeredFromHomeKey));      } -    public void toggleRecents() { +    public void toggleRecents(int growTarget) {          // Skip this toggle if we are already waiting to trigger recents via alt-tab          if (mFastAltTabTrigger.isDozing()) {              return; @@ -338,7 +343,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener                  }                  // Otherwise, start the recents activity -                startRecentsActivity(topTask, isTopTaskHome.value, true /* animate */); +                startRecentsActivity(topTask, isTopTaskHome.value, true /* animate */, growTarget);                  // Only close the other system windows if we are actually showing recents                  ssp.sendCloseSystemWindows(BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS); @@ -369,7 +374,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener                  // At this point, we don't know anything about the stack state.  So only calculate                  // the dimensions of the thumbnail that we need for the transition into Recents, but                  // do not draw it until we construct the activity options when we start Recents -                updateHeaderBarLayout(stack); +                updateHeaderBarLayout(stack, null /* window rect override*/);              }          }      } @@ -535,7 +540,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener                      dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,                      false /* animate */,                      true /* launchedWhileDockingTask*/, -                    false /* fromHome */); +                    false /* fromHome */, +                    DividerView.INVALID_RECENTS_GROW_TARGET);          }      } @@ -574,12 +580,17 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener       * since the last call, it will attempt to re-measure and layout the header bar to the new size.       *       * @param stack the stack to initialize the stack layout with +     * @param windowRectOverride the rectangle to use when calculating the stack state which can +     *                           be different from the current window rect if recents is resizing +     *                           while being launched       */ -    private void updateHeaderBarLayout(TaskStack stack) { +    private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {          SystemServicesProxy ssp = Recents.getSystemServices();          Rect systemInsets = new Rect();          ssp.getStableInsets(systemInsets); -        Rect windowRect = ssp.getWindowRect(); +        Rect windowRect = windowRectOverride != null +                ? new Rect(windowRectOverride) +                : ssp.getWindowRect();          // When docked, the nav bar insets are consumed and the activity is measured without insets.          // However, the window bounds include the insets, so we need to subtract them here to make          // them identical. @@ -682,7 +693,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener       * Creates the activity options for an app->recents transition.       */      private ActivityOptions getThumbnailTransitionActivityOptions( -            ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) { +            ActivityManager.RunningTaskInfo topTask, TaskStackView stackView, +            Rect windowOverrideRect) {          if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {              ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();              ArrayList<Task> tasks = stackView.getStack().getStackTasks(); @@ -696,7 +708,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener                  Task task = tasks.get(i);                  if (task.isFreeformTask()) {                      mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task, -                                    stackScroller.getStackScroll(), mTmpTransform, null); +                            stackScroller.getStackScroll(), mTmpTransform, null, +                            windowOverrideRect);                      Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,                              mThumbTransitionBitmapCache);                      Rect toTaskRect = new Rect(); @@ -711,7 +724,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener          } else {              // Update the destination rect              Task toTask = new Task(); -            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask); +            TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask, +                    windowOverrideRect);              Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,                      mThumbTransitionBitmapCache);              if (thumbnail != null) { @@ -729,7 +743,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener       * Returns the transition rect for the given task id.       */      private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView, -            Task runningTaskOut) { +            Task runningTaskOut, Rect windowOverrideRect) {          // Find the running task in the TaskStack          TaskStack stack = stackView.getStack();          Task launchTask = stack.getLaunchTarget(); @@ -745,7 +759,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener          stackView.updateLayoutAlgorithm(true /* boundScroll */);          stackView.updateToInitialState();          stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask, -                stackView.getScroller().getStackScroll(), mTmpTransform, null); +                stackView.getScroller().getStackScroll(), mTmpTransform, null, windowOverrideRect);          return mTmpTransform;      } @@ -788,7 +802,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener       * Shows the recents activity       */      protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, -            boolean isTopTaskHome, boolean animate) { +            boolean isTopTaskHome, boolean animate, int growTarget) {          RecentsTaskLoader loader = Recents.getTaskLoader();          RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); @@ -820,7 +834,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener          preloadIcon(topTask);          // Update the header bar if necessary -        updateHeaderBarLayout(stack); +        Rect windowOverrideRect = getWindowRectOverride(growTarget); +        updateHeaderBarLayout(stack, windowOverrideRect);          // Prepare the dummy stack for the transition          TaskStackLayoutAlgorithm.VisibilityReport stackVr = @@ -838,7 +853,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener          ActivityOptions opts;          if (useThumbnailTransition) {              // Try starting with a thumbnail transition -            opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView); +            opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView, +                    windowOverrideRect);          } else {              // If there is no thumbnail transition, but is launching from home into recents, then              // use a quick home transition @@ -850,6 +866,18 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener          mLastToggleTime = SystemClock.elapsedRealtime();      } +    private Rect getWindowRectOverride(int growTarget) { +        if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) { +            return null; +        } +        Rect result = new Rect(); +        Rect displayRect = Recents.getSystemServices().getDisplayRect(); +        DockedDividerUtils.calculateBoundsForPosition(growTarget, WindowManager.DOCKED_BOTTOM, +                result, displayRect.width(), displayRect.height(), +                Recents.getSystemServices().getDockedDividerSize(mContext)); +        return result; +    } +      /**       * Starts the recents activity.       */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java index 257bda2e147a..defc6ed042bc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java @@ -57,13 +57,15 @@ public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub {      @Override      public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate, -            boolean reloadTasks, boolean fromHome) throws RemoteException { +            boolean reloadTasks, boolean fromHome, int growTarget) +            throws RemoteException {          SomeArgs args = SomeArgs.obtain();          args.argi1 = triggeredFromAltTab ? 1 : 0;          args.argi2 = draggingInRecents ? 1 : 0;          args.argi3 = animate ? 1 : 0;          args.argi4 = reloadTasks ? 1 : 0;          args.argi5 = fromHome ? 1 : 0; +        args.argi6 = growTarget;          mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args));      } @@ -75,8 +77,8 @@ public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub {      }      @Override -    public void toggleRecents() throws RemoteException { -        mHandler.sendEmptyMessage(MSG_TOGGLE_RECENTS); +    public void toggleRecents(int growTarget) throws RemoteException { +        mHandler.sendMessage(mHandler.obtainMessage(MSG_TOGGLE_RECENTS, growTarget));      }      @Override @@ -119,13 +121,13 @@ public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub {                  case MSG_SHOW_RECENTS:                      SomeArgs args = (SomeArgs) msg.obj;                      mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0, -                            args.argi4 != 0, args.argi5 != 0); +                            args.argi4 != 0, args.argi5 != 0, args.argi6);                      break;                  case MSG_HIDE_RECENTS:                      mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0);                      break;                  case MSG_TOGGLE_RECENTS: -                    mImpl.toggleRecents(); +                    mImpl.toggleRecents(msg.arg1);                      break;                  case MSG_ON_CONFIGURATION_CHANGED:                      mImpl.onConfigurationChanged(); diff --git a/core/java/android/net/UidRange.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java index f9be628c1673..d9b00271b31e 100644 --- a/core/java/android/net/UidRange.aidl +++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java @@ -1,5 +1,5 @@  /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2016 The Android Open Source Project   *   * Licensed under the Apache License, Version 2.0 (the "License");   * you may not use this file except in compliance with the License. @@ -11,14 +11,16 @@   * distributed under the License is distributed on an "AS IS" BASIS,   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License   */ -package android.net; +package com.android.systemui.recents.events.ui; + +import com.android.systemui.recents.events.EventBus;  /** - * An inclusive range of UIDs. - * - * {@hide} + * Sent when recents is about to grow in multi-window mode when entering recents.   */ -parcelable UidRange; +public class RecentsGrowingEvent extends EventBus.Event { + +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java index dc0d1f1fe465..18b9263564bb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java @@ -49,7 +49,7 @@ public class RecentsTvImpl extends RecentsImpl{      @Override      protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, -            boolean isTopTaskHome, boolean animate) { +            boolean isTopTaskHome, boolean animate, int growTarget) {          RecentsTaskLoader loader = Recents.getTaskLoader();          // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index 04f10ef8e893..1238c637e006 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -302,7 +302,8 @@ public class RecentsTransitionHelper {                  specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));              } else {                  mTmpTransform.fillIn(taskView); -                stackLayout.transformToScreenCoordinates(mTmpTransform); +                stackLayout.transformToScreenCoordinates(mTmpTransform, +                        null /* windowOverrideRect */);                  specs.add(composeAnimationSpec(stackView, taskView, mTmpTransform,                          true /* addHeaderBitmap */));              } @@ -324,7 +325,8 @@ public class RecentsTransitionHelper {                      specs.add(composeOffscreenAnimationSpec(t, offscreenTaskRect));                  } else {                      mTmpTransform.fillIn(taskView); -                    stackLayout.transformToScreenCoordinates(mTmpTransform); +                    stackLayout.transformToScreenCoordinates(mTmpTransform, +                            null /* windowOverrideRect */);                      specs.add(composeAnimationSpec(stackView, tv, mTmpTransform,                              true /* addHeaderBitmap */));                  } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index 774e4e9cd086..0022d66103b1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -830,18 +830,23 @@ public class TaskStackLayoutAlgorithm {       * Like {@link #getStackTransform}, but in screen coordinates       */      public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll, -            TaskViewTransform transformOut, TaskViewTransform frontTransform) { +            TaskViewTransform transformOut, TaskViewTransform frontTransform, +            Rect windowOverrideRect) {          TaskViewTransform transform = getStackTransform(task, stackScroll, mFocusState,                  transformOut, frontTransform, true /* forceUpdate */,                  false /* ignoreTaskOverrides */); -        return transformToScreenCoordinates(transform); +        return transformToScreenCoordinates(transform, windowOverrideRect);      }      /** -     * Transforms the given {@param transformOut} to the screen coordinates. +     * Transforms the given {@param transformOut} to the screen coordinates, overriding the current +     * window rectangle with {@param windowOverrideRect} if non-null.       */ -    public TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut) { -        Rect windowRect = Recents.getSystemServices().getWindowRect(); +    public TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut, +            Rect windowOverrideRect) { +        Rect windowRect = windowOverrideRect != null +                ? windowOverrideRect +                : Recents.getSystemServices().getWindowRect();          transformOut.rect.offset(windowRect.left, windowRect.top);          return transformOut;      } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 6176d99a7c17..610b4e104538 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -72,6 +72,7 @@ import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;  import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;  import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;  import com.android.systemui.recents.events.ui.DismissTaskViewEvent; +import com.android.systemui.recents.events.ui.RecentsGrowingEvent;  import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;  import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;  import com.android.systemui.recents.events.ui.UserInteractionEvent; @@ -189,6 +190,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal      private TaskViewTransform mTmpTransform = new TaskViewTransform();      private ArrayList<TaskViewTransform> mTmpTaskTransforms = new ArrayList<>();      private int[] mTmpIntPair = new int[2]; +    private boolean mResetToInitialStateWhenResized; +    private int mLastWidth; +    private int mLastHeight;      // A convenience update listener to request updating clipping of tasks      private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener = @@ -1164,9 +1168,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal          // If this is the first layout, then scroll to the front of the stack, then update the          // TaskViews with the stack so that we can lay them out -        if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) { -            if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY) { +        boolean resetToInitialState = (width != mLastWidth || height != mLastHeight) +                && mResetToInitialStateWhenResized; +        if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE +                || resetToInitialState) { +            if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY || resetToInitialState) {                  updateToInitialState(); +                mResetToInitialStateWhenResized = false;              }              if (!mAwaitingFirstLayout) {                  mInitialState = INITIAL_STATE_UPDATE_NONE; @@ -1186,6 +1194,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal          }          setMeasuredDimension(width, height); +        mLastWidth = width; +        mLastHeight = height;          mInMeasureLayout = false;      } @@ -1765,6 +1775,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal                  mTmpTransform, null);          mTmpTransform.scale = finalScale;          mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1; +        mTmpTransform.dimAlpha = 0f;          updateTaskViewToTransform(event.taskView, mTmpTransform,                  new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));      } @@ -1972,6 +1983,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal          }      } +    public final void onBusEvent(RecentsGrowingEvent event) { +        mResetToInitialStateWhenResized = true; +    } +      public void reloadOnConfigurationChange() {          mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());          mLayoutAlgorithm.reloadOnConfigurationChange(getContext()); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 67c4008b4dc6..44a167bcf7cf 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -32,6 +32,7 @@ import android.graphics.Region.Op;  import android.hardware.display.DisplayManager;  import android.os.Bundle;  import android.util.AttributeSet; +import android.util.MutableInt;  import android.view.Display;  import android.view.DisplayInfo;  import android.view.GestureDetector; @@ -66,6 +67,7 @@ import com.android.systemui.recents.events.activity.DockedTopTaskEvent;  import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;  import com.android.systemui.recents.events.activity.UndockingTaskEvent;  import com.android.systemui.recents.events.ui.RecentsDrawnEvent; +import com.android.systemui.recents.events.ui.RecentsGrowingEvent;  import com.android.systemui.recents.misc.SystemServicesProxy;  import com.android.systemui.stackdivider.events.StartedDragingEvent;  import com.android.systemui.stackdivider.events.StoppedDragingEvent; @@ -81,6 +83,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,      static final long TOUCH_ANIMATION_DURATION = 150;      static final long TOUCH_RELEASE_ANIMATION_DURATION = 200; +    public static final int INVALID_RECENTS_GROW_TARGET = -1; +      private static final int LOG_VALUE_RESIZE_50_50 = 0;      private static final int LOG_VALUE_RESIZE_DOCKED_SMALLER = 1;      private static final int LOG_VALUE_RESIZE_DOCKED_LARGER = 2; @@ -88,7 +92,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,      private static final int LOG_VALUE_UNDOCK_MAX_DOCKED = 0;      private static final int LOG_VALUE_UNDOCK_MAX_OTHER = 1; -      private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;      private static final boolean SWAPPING_ENABLED = false; @@ -154,31 +157,62 @@ public class DividerView extends FrameLayout implements OnTouchListener,          public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {              super.onInitializeAccessibilityNodeInfo(host, info);              if (isHorizontalDivision()) { -                info.addAction(new AccessibilityAction(R.id.action_move_up, -                        mContext.getString(R.string.accessibility_action_divider_move_up))); -                info.addAction(new AccessibilityAction(R.id.action_move_down, -                        mContext.getString(R.string.accessibility_action_divider_move_down))); +                info.addAction(new AccessibilityAction(R.id.action_move_tl_full, +                        mContext.getString(R.string.accessibility_action_divider_top_full))); +                if (mSnapAlgorithm.isFirstSplitTargetAvailable()) { +                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70, +                            mContext.getString(R.string.accessibility_action_divider_top_70))); +                } +                info.addAction(new AccessibilityAction(R.id.action_move_tl_50, +                        mContext.getString(R.string.accessibility_action_divider_top_50))); +                if (mSnapAlgorithm.isLastSplitTargetAvailable()) { +                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30, +                            mContext.getString(R.string.accessibility_action_divider_top_30))); +                } +                info.addAction(new AccessibilityAction(R.id.action_move_rb_full, +                        mContext.getString(R.string.accessibility_action_divider_bottom_full)));              } else { -                info.addAction(new AccessibilityAction(R.id.action_move_left, -                        mContext.getString(R.string.accessibility_action_divider_move_left))); -                info.addAction(new AccessibilityAction(R.id.action_move_right, -                        mContext.getString(R.string.accessibility_action_divider_move_right))); +                info.addAction(new AccessibilityAction(R.id.action_move_tl_full, +                        mContext.getString(R.string.accessibility_action_divider_left_full))); +                if (mSnapAlgorithm.isFirstSplitTargetAvailable()) { +                    info.addAction(new AccessibilityAction(R.id.action_move_tl_70, +                            mContext.getString(R.string.accessibility_action_divider_left_70))); +                } +                info.addAction(new AccessibilityAction(R.id.action_move_tl_50, +                        mContext.getString(R.string.accessibility_action_divider_left_50))); +                if (mSnapAlgorithm.isLastSplitTargetAvailable()) { +                    info.addAction(new AccessibilityAction(R.id.action_move_tl_30, +                            mContext.getString(R.string.accessibility_action_divider_left_30))); +                } +                info.addAction(new AccessibilityAction(R.id.action_move_rb_full, +                        mContext.getString(R.string.accessibility_action_divider_right_full)));              }          }          @Override          public boolean performAccessibilityAction(View host, int action, Bundle args) { -            if (action == R.id.action_move_up || action == R.id.action_move_down -                    || action == R.id.action_move_left || action == R.id.action_move_right) { -                int position = getCurrentPosition(); -                SnapTarget currentTarget = mSnapAlgorithm.calculateSnapTarget( -                        position, 0 /* velocity */); -                SnapTarget nextTarget = -                        action == R.id.action_move_up || action == R.id.action_move_left -                                ? mSnapAlgorithm.getPreviousTarget(currentTarget) -                                : mSnapAlgorithm.getNextTarget(currentTarget); +            int currentPosition = getCurrentPosition(); +            SnapTarget nextTarget = null; +            switch (action) { +                case R.id.action_move_tl_full: +                    nextTarget = mSnapAlgorithm.getDismissEndTarget(); +                    break; +                case R.id.action_move_tl_70: +                    nextTarget = mSnapAlgorithm.getLastSplitTarget(); +                    break; +                case R.id.action_move_tl_50: +                    nextTarget = mSnapAlgorithm.getMiddleTarget(); +                    break; +                case R.id.action_move_tl_30: +                    nextTarget = mSnapAlgorithm.getFirstSplitTarget(); +                    break; +                case R.id.action_move_rb_full: +                    nextTarget = mSnapAlgorithm.getDismissStartTarget(); +                    break; +            } +            if (nextTarget != null) {                  startDragging(true /* animate */, false /* touching */); -                stopDragging(getCurrentPosition(), nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN); +                stopDragging(currentPosition, nextTarget, 250, Interpolators.FAST_OUT_SLOW_IN);                  return true;              }              return super.performAccessibilityAction(host, action, args); @@ -997,6 +1031,24 @@ public class DividerView extends FrameLayout implements OnTouchListener,                  mBackground.getRight(), mBackground.getBottom(), Op.UNION);      } +    /** +     * Checks whether recents will grow when invoked. This happens in multi-window when recents is +     * very small. When invoking recents, we shrink the docked stack so recents has more space. +     * +     * @return the position of the divider when recents grows, or +     *         {@link #INVALID_RECENTS_GROW_TARGET} if recents won't grow +     */ +    public int growsRecents() { +        boolean result = mGrowRecents +                && mWindowManagerProxy.getDockSide() == WindowManager.DOCKED_TOP +                && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position; +        if (result) { +            return getSnapAlgorithm().getMiddleTarget().position; +        } else { +            return INVALID_RECENTS_GROW_TARGET; +        } +    } +      public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {          if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP                  && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) { @@ -1036,7 +1088,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,          if (mGrowAfterRecentsDrawn) {              mGrowAfterRecentsDrawn = false;              updateDockSide(); -            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 250, +            EventBus.getDefault().send(new RecentsGrowingEvent()); +            stopDragging(getCurrentPosition(), mSnapAlgorithm.getMiddleTarget(), 336,                      Interpolators.FAST_OUT_SLOW_IN);          }      } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java index 177296bc8c03..18834edaff05 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivity.java @@ -18,6 +18,7 @@ package com.android.systemui.stackdivider;  import android.annotation.Nullable;  import android.app.Activity; +import android.app.ActivityManager;  import android.os.Bundle;  import android.view.KeyEvent;  import android.view.MotionEvent; @@ -75,4 +76,9 @@ public class ForcedResizableInfoActivity extends Activity implements OnTouchList          finish();          return true;      } + +    @Override +    public void setTaskDescription(ActivityManager.TaskDescription taskDescription) { +        // Do nothing +    }  } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index cb1128bfca49..2d5b6d45e801 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1318,7 +1318,7 @@ public abstract class BaseStatusBar extends SystemUI implements      protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {          if (mRecents != null) {              sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS); -            mRecents.showRecents(triggeredFromAltTab, fromHome, getStatusBarView()); +            mRecents.showRecents(triggeredFromAltTab, fromHome);          }      } @@ -1330,7 +1330,7 @@ public abstract class BaseStatusBar extends SystemUI implements      protected void toggleRecents() {          if (mRecents != null) { -            mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView()); +            mRecents.toggleRecents(mDisplay);          }      } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java index 32c26ba8ba13..0c1891e1fde9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/FakeShadowView.java @@ -25,6 +25,7 @@ import android.view.ViewGroup;  import android.view.ViewOutlineProvider;  import android.widget.LinearLayout; +import com.android.systemui.R;  import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;  /** @@ -32,6 +33,7 @@ import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;   */  public class FakeShadowView extends AlphaOptimizedFrameLayout {      public static final float SHADOW_SIBLING_TRESHOLD = 0.1f; +    private final int mShadowMinHeight;      private View mFakeShadow;      private float mOutlineAlpha; @@ -64,6 +66,8 @@ public class FakeShadowView extends AlphaOptimizedFrameLayout {              }          });          addView(mFakeShadow); +        mShadowMinHeight = Math.max(1, context.getResources() +                .getDimensionPixelSize(R.dimen.notification_divider_height));      }      public void setFakeShadowTranslationZ(float fakeShadowTranslationZ, float outlineAlpha, @@ -72,6 +76,7 @@ public class FakeShadowView extends AlphaOptimizedFrameLayout {              mFakeShadow.setVisibility(INVISIBLE);          } else {              mFakeShadow.setVisibility(VISIBLE); +            fakeShadowTranslationZ = Math.max(mShadowMinHeight, fakeShadowTranslationZ);              mFakeShadow.setTranslationZ(fakeShadowTranslationZ);              mFakeShadow.setTranslationX(outlineTranslation);              mFakeShadow.setTranslationY(shadowYEnd - mFakeShadow.getHeight()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index 915b56563d33..1a9a40b24332 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -43,9 +43,9 @@ public class KeyguardAffordanceHelper {      private static final int HINT_CIRCLE_OPEN_DURATION = 500;      private final Context mContext; +    private final Callback mCallback;      private FlingAnimationUtils mFlingAnimationUtils; -    private Callback mCallback;      private VelocityTracker mVelocityTracker;      private boolean mSwipingInProgress;      private float mInitialTouchX; @@ -318,12 +318,11 @@ public class KeyguardAffordanceHelper {          float vel = getCurrentVelocity(lastX, lastY);          // We snap back if the current translation is not far enough -        boolean snapBack; -        if (mFalsingManager.isFalseTouch()) { -            snapBack = mFalsingManager.isFalseTouch(); -        } else { -            snapBack = isBelowFalsingThreshold(); +        boolean snapBack = false; +        if (mCallback.needsAntiFalsing()) { +            snapBack = snapBack || mFalsingManager.isFalseTouch();          } +        snapBack = snapBack || isBelowFalsingThreshold();          // or if the velocity is in the opposite direction.          boolean velIsInWrongDirection = vel * mTranslation < 0; @@ -582,5 +581,7 @@ public class KeyguardAffordanceHelper {           * @return The factor the minimum swipe amount should be multiplied with.           */          float getAffordanceFalsingFactor(); + +        boolean needsAntiFalsing();      }  } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java index 92f3585f43ef..ef19d95c1195 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java @@ -16,6 +16,7 @@  package com.android.systemui.statusbar.phone; +import android.annotation.Nullable;  import android.app.ActivityManager;  import android.app.IWallpaperManager;  import android.app.IWallpaperManagerCallback; @@ -26,8 +27,9 @@ import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.graphics.Rect;  import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable;  import android.graphics.drawable.DrawableWrapper; -import android.os.Bundle; +import android.os.AsyncTask;  import android.os.Handler;  import android.os.ParcelFileDescriptor;  import android.os.RemoteException; @@ -46,9 +48,7 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen      private static final String TAG = "LockscreenWallpaper"; -    private final Context mContext;      private final PhoneStatusBar mBar; -    private final IWallpaperManager mService;      private final WallpaperManager mWallpaperManager;      private final Handler mH; @@ -58,68 +58,74 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen      // The user selected in the UI, or null if no user is selected or UI doesn't support selecting      // users.      private UserHandle mSelectedUser; +    private AsyncTask<Void, Void, LoaderResult> mLoader;      public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) { -        mContext = ctx;          mBar = bar;          mH = h; -        mService = IWallpaperManager.Stub.asInterface( -                ServiceManager.getService(Context.WALLPAPER_SERVICE));          mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);          mCurrentUserId = ActivityManager.getCurrentUser(); +        IWallpaperManager service = IWallpaperManager.Stub.asInterface( +                ServiceManager.getService(Context.WALLPAPER_SERVICE));          try { -            mService.setLockWallpaperCallback(this); +            service.setLockWallpaperCallback(this);          } catch (RemoteException e) {              Log.e(TAG, "System dead?" + e);          }      }      public Bitmap getBitmap() { -        try { -            if (mCached) { -                return mCache; -            } -            if (!mService.isWallpaperSupported(mContext.getOpPackageName())) { -                mCached = true; -                mCache = null; -                return null; +        if (mCached) { +            return mCache; +        } +        if (!mWallpaperManager.isWallpaperSupported()) { +            mCached = true; +            mCache = null; +            return null; +        } + +        LoaderResult result = loadBitmap(mCurrentUserId, mSelectedUser); +        if (result.success) { +            mCached = true; +            mCache = result.bitmap; +        } +        return mCache; +    } + +    public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) { +        // May be called on any thread - only use thread safe operations. + +        // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK +        // wallpaper. +        final int lockWallpaperUserId = +                selectedUser != null ? selectedUser.getIdentifier() : currentUserId; +        ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile( +                WallpaperManager.FLAG_LOCK, lockWallpaperUserId); + +        if (fd != null) { +            try { +                BitmapFactory.Options options = new BitmapFactory.Options(); +                return LoaderResult.success(BitmapFactory.decodeFileDescriptor( +                        fd.getFileDescriptor(), null, options)); +            } catch (OutOfMemoryError e) { +                Log.w(TAG, "Can't decode file", e); +                return LoaderResult.fail(); +            } finally { +                IoUtils.closeQuietly(fd);              } -            // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK -            // wallpaper. -            final int lockWallpaperUserId = -                    mSelectedUser != null ? mSelectedUser.getIdentifier() : mCurrentUserId; -            ParcelFileDescriptor fd = mService.getWallpaper(null, WallpaperManager.FLAG_LOCK, -                    new Bundle(), lockWallpaperUserId); -            if (fd != null) { -                try { -                    BitmapFactory.Options options = new BitmapFactory.Options(); -                    mCache = BitmapFactory.decodeFileDescriptor( -                            fd.getFileDescriptor(), null, options); -                    mCached = true; -                    return mCache; -                } catch (OutOfMemoryError e) { -                    Log.w(TAG, "Can't decode file", e); -                    return null; -                } finally { -                    IoUtils.closeQuietly(fd); -                } +        } else { +            if (selectedUser != null && selectedUser.getIdentifier() != currentUserId) { +                // When selected user is different from the current user, show the selected +                // user's static wallpaper. +                return LoaderResult.success( +                        mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier())); +              } else { -                mCached = true; -                if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) { -                    // When selected user is different from the current user, show the selected -                    // user's static wallpaper. -                    mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier()); -                } else { -                    // When there is no selected user, or it's same as the current user, show the -                    // system (possibly dynamic) wallpaper for the selected user. -                    mCache = null; -                } -                return mCache; +                // When there is no selected user, or it's same as the current user, show the +                // system (possibly dynamic) wallpaper for the selected user. +                return LoaderResult.success(null);              } -        } catch (RemoteException e) { -            Log.e(TAG, "System dead?" + e); -            return null;          }      } @@ -135,14 +141,16 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen              return;          }          mSelectedUser = selectedUser; - -        mH.removeCallbacks(this); -        mH.post(this); +        postUpdateWallpaper();      }      @Override      public void onWallpaperChanged() {          // Called on Binder thread. +        postUpdateWallpaper(); +    } + +    private void postUpdateWallpaper() {          mH.removeCallbacks(this);          mH.post(this);      } @@ -150,10 +158,52 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen      @Override      public void run() {          // Called in response to onWallpaperChanged on the main thread. -        mCached = false; -        mCache = null; -        getBitmap(); -        mBar.updateMediaMetaData(true /* metaDataChanged */, true /* allowEnterAnimation */); + +        if (mLoader != null) { +            mLoader.cancel(false /* interrupt */); +        } + +        final int currentUser = mCurrentUserId; +        final UserHandle selectedUser = mSelectedUser; +        mLoader = new AsyncTask<Void, Void, LoaderResult>() { +            @Override +            protected LoaderResult doInBackground(Void... params) { +                return loadBitmap(currentUser, selectedUser); +            } + +            @Override +            protected void onPostExecute(LoaderResult result) { +                super.onPostExecute(result); +                if (isCancelled()) { +                    return; +                } +                if (result.success) { +                    mCached = true; +                    mCache = result.bitmap; +                    mBar.updateMediaMetaData( +                            true /* metaDataChanged */, true /* allowEnterAnimation */); +                } +                mLoader = null; +            } +        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); +    } + +    private static class LoaderResult { +        public final boolean success; +        public final Bitmap bitmap; + +        LoaderResult(boolean success, Bitmap bitmap) { +            this.success = success; +            this.bitmap = bitmap; +        } + +        static LoaderResult success(Bitmap b) { +            return new LoaderResult(true, b); +        } + +        static LoaderResult fail() { +            return new LoaderResult(false, null); +        }      }      /** @@ -161,12 +211,16 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen       */      public static class WallpaperDrawable extends DrawableWrapper { -        private Bitmap mBackground; -        private Rect mTmpRect = new Rect(); +        private final ConstantState mState; +        private final Rect mTmpRect = new Rect();          public WallpaperDrawable(Resources r, Bitmap b) { -            super(new BitmapDrawable(r, b)); -            mBackground = b; +            this(r, new ConstantState(b)); +        } + +        private WallpaperDrawable(Resources r, ConstantState state) { +            super(new BitmapDrawable(r, state.mBackground)); +            mState = state;          }          @Override @@ -183,8 +237,8 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen          protected void onBoundsChange(Rect bounds) {              int vwidth = getBounds().width();              int vheight = getBounds().height(); -            int dwidth = mBackground.getWidth(); -            int dheight = mBackground.getHeight(); +            int dwidth = mState.mBackground.getWidth(); +            int dheight = mState.mBackground.getHeight();              float scale;              float dx = 0, dy = 0; @@ -207,5 +261,35 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen              super.onBoundsChange(mTmpRect);          } + +        @Override +        public ConstantState getConstantState() { +            return mState; +        } + +        static class ConstantState extends Drawable.ConstantState { + +            private final Bitmap mBackground; + +            ConstantState(Bitmap background) { +                mBackground = background; +            } + +            @Override +            public Drawable newDrawable() { +                return newDrawable(null); +            } + +            @Override +            public Drawable newDrawable(@Nullable Resources res) { +                return new WallpaperDrawable(res, this); +            } + +            @Override +            public int getChangingConfigurations() { +                // DrawableWrapper already handles this for us. +                return 0; +            } +        }      }  } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 62c0fa9fe9e6..48cf631bb683 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -701,7 +701,7 @@ public class NotificationPanelView extends PanelView implements      }      private boolean isFalseTouch() { -        if (mStatusBarState != StatusBarState.KEYGUARD) { +        if (!needsAntiFalsing()) {              return false;          }          if (mFalsingManager.isClassiferEnabled()) { @@ -1941,6 +1941,11 @@ public class NotificationPanelView extends PanelView implements      }      @Override +    public boolean needsAntiFalsing() { +        return mStatusBarState == StatusBarState.KEYGUARD; +    } + +    @Override      protected float getPeekHeight() {          if (mNotificationStackScroller.getNotGoneChildCount() > 0) {              return mNotificationStackScroller.getPeekHeight(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index d3f3b2d58e1e..712f8143cbc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -2021,7 +2021,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,              if (metaDataChanged) {                  if (mBackdropBack.getDrawable() != null) {                      Drawable drawable = -                            mBackdropBack.getDrawable().getConstantState().newDrawable().mutate(); +                            mBackdropBack.getDrawable().getConstantState() +                                    .newDrawable(mBackdropFront.getResources()).mutate();                      mBackdropFront.setImageDrawable(drawable);                      if (mScrimSrcModeEnabled) {                          mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 82496acbe4ef..493b23f7a258 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -209,7 +209,7 @@ public class QSTileHost implements QSTile.Host, Tunable {          // already logged      } -    public void animateExpandQS() { +    public void animateToggleQSExpansion() {          // TODO: Better path to animated panel expansion.          mHeader.performClick();      } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index 2b03dfb841c3..b8e069d3fe5b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -106,6 +106,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements          mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);          mDateTimeGroup.setPivotX(0);          mDateTimeGroup.setPivotY(0); +        boolean showDate = getResources().getBoolean(R.bool.quick_settings_show_date); +        findViewById(R.id.date).setVisibility(showDate ? View.VISIBLE : View.GONE);          mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 40eb71d8327b..40dacd3b991d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -791,7 +791,7 @@ public class NetworkControllerImpl extends BroadcastReceiver      private SubscriptionInfo addSignalController(int id, int simSlotIndex) {          SubscriptionInfo info = new SubscriptionInfo(id, "", simSlotIndex, "", "", 0, 0, "", 0, -                null, 0, 0, ""); +                null, 0, 0, "", SubscriptionManager.SIM_PROVISIONED);          mMobileSignalControllers.put(id, new MobileSignalController(mContext,                  mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, info,                  mSubDefaults, mReceiverHandler.getLooper())); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index d900b378c2c8..2b29c6b6367a 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -60,7 +60,6 @@ import android.os.PowerManager;  import android.os.Process;  import android.os.RemoteCallbackList;  import android.os.RemoteException; -import android.os.ServiceManager;  import android.os.SystemClock;  import android.os.UserHandle;  import android.os.UserManager; @@ -92,7 +91,6 @@ import android.view.accessibility.IAccessibilityManagerClient;  import com.android.internal.R;  import com.android.internal.content.PackageMonitor;  import com.android.internal.os.SomeArgs; -import com.android.internal.statusbar.IStatusBarService;  import com.android.server.LocalServices;  import com.android.server.statusbar.StatusBarManagerInternal; @@ -3315,13 +3313,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {          private void openRecents() {              final long token = Binder.clearCallingIdentity(); -            IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( -                    ServiceManager.getService("statusbar")); -            try { -                statusBarService.toggleRecentApps(); -            } catch (RemoteException e) { -                Slog.e(LOG_TAG, "Error toggling recent apps."); -            } +            StatusBarManagerInternal statusBarService = LocalServices.getService( +                    StatusBarManagerInternal.class); +            statusBarService.toggleRecentApps();              Binder.restoreCallingIdentity(token);          } diff --git a/services/core/Android.mk b/services/core/Android.mk index a248aa332225..860f60a01936 100644 --- a/services/core/Android.mk +++ b/services/core/Android.mk @@ -13,6 +13,9 @@ LOCAL_SRC_FILES += \      ../../../../system/netd/server/binder/android/net/INetd.aidl \      ../../../../system/netd/server/binder/android/net/metrics/IDnsEventListener.aidl \ +LOCAL_AIDL_INCLUDES += \ +    system/netd/server/binder +  LOCAL_JAVA_LIBRARIES := services.net telephony-common  LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index d61b561b158e..6c0517387176 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -690,17 +690,17 @@ public class LockSettingsService extends ILockSettings.Stub {          final IProgressListener listener = new IProgressListener.Stub() {              @Override              public void onStarted(int id, Bundle extras) throws RemoteException { -                // Ignored +                Log.d(TAG, "unlockUser started");              }              @Override              public void onProgress(int id, int progress, Bundle extras) throws RemoteException { -                // Ignored +                Log.d(TAG, "unlockUser progress " + progress);              }              @Override              public void onFinished(int id, Bundle extras) throws RemoteException { -                Log.d(TAG, "unlockUser finished!"); +                Log.d(TAG, "unlockUser finished");                  latch.countDown();              }          }; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5d83a6e5ac97..d7afc13e022c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1945,6 +1945,9 @@ public final class ActivityManagerService extends ActivityManagerNative                      startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);                  }                  installEncryptionUnawareProviders(userId); +                if (msg.obj instanceof ProgressReporter) { +                    ((ProgressReporter) msg.obj).finish(); +                }                  break;              }              case SYSTEM_USER_CURRENT_MSG: { @@ -20103,6 +20106,9 @@ public final class ActivityManagerService extends ActivityManagerNative                  if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");              }          } +        if (memFactor != mLastMemoryLevel) { +            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel); +        }          mLastMemoryLevel = memFactor;          mLastNumProcesses = mLruProcesses.size();          boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now); @@ -20979,6 +20985,36 @@ public final class ActivityManagerService extends ActivityManagerNative                  mStackSupervisor.setDockedStackMinimized(minimized);              }          } + +        @Override +        public void killForegroundAppsForUser(int userHandle) { +            synchronized (ActivityManagerService.this) { +                final ArrayList<ProcessRecord> procs = new ArrayList<>(); +                final int NP = mProcessNames.getMap().size(); +                for (int ip = 0; ip < NP; ip++) { +                    final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip); +                    final int NA = apps.size(); +                    for (int ia = 0; ia < NA; ia++) { +                        final ProcessRecord app = apps.valueAt(ia); +                        if (app.persistent) { +                            // We don't kill persistent processes. +                            continue; +                        } +                        if (app.removed) { +                            procs.add(app); +                        } else if (app.userId == userHandle && app.foregroundActivities) { +                            app.removed = true; +                            procs.add(app); +                        } +                    } +                } + +                final int N = procs.size(); +                for (int i = 0; i < N; i++) { +                    removeProcessLocked(procs.get(i), false, true, "kill all fg"); +                } +            } +        }      }      private final class SleepTokenImpl extends SleepToken { diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 6cd6ff43b5ce..2516f5df4cbf 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -58,8 +58,8 @@ import com.android.internal.app.IBatteryStats;  import com.android.internal.os.BatteryStatsHelper;  import com.android.internal.os.BatteryStatsImpl;  import com.android.internal.os.PowerProfile; -import com.android.server.FgThread;  import com.android.server.LocalServices; +import com.android.server.ServiceThread;  import java.io.File;  import java.io.FileDescriptor; @@ -176,7 +176,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub      BatteryStatsService(File systemDir, Handler handler) {          // Our handler here will be accessing the disk, use a different thread than          // what the ActivityManagerService gave us (no I/O on that one!). -        mHandler = new BatteryStatsHandler(FgThread.getHandler().getLooper()); +        final ServiceThread thread = new ServiceThread("batterystats-sync", +                Process.THREAD_PRIORITY_DEFAULT, true); +        thread.start(); +        mHandler = new BatteryStatsHandler(thread.getLooper());          // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.          mStats = new BatteryStatsImpl(systemDir, handler, mHandler); @@ -209,6 +212,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub          synchronized (mStats) {              mStats.shutdownLocked();          } + +        // Shutdown the thread we made. +        mHandler.getLooper().quit();      }      public static IBatteryStats getService() { diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags index 2329b2f82bb7..2762df6b8ad5 100644 --- a/services/core/java/com/android/server/am/EventLogTags.logtags +++ b/services/core/java/com/android/server/am/EventLogTags.logtags @@ -108,3 +108,7 @@ option java_package com.android.server.am  30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)  # The activity's onStop has been called.  30049 am_on_stop_called (User|1|5),(Component Name|3),(Reason|3) + +# Report changing memory conditions (Values are ProcessStats.ADJ_MEM_FACTOR* constants) +30050 am_mem_factor (Current|1|5),(Previous|1|5) + diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java index 9fb51c19a9de..4a87941af8b9 100644 --- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java +++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java @@ -35,12 +35,12 @@ import java.util.Map;  public class HealthStatsBatteryStatsWriter { -    private final long mNowRealtime; -    private final long mNowUptime; +    private final long mNowRealtimeMs; +    private final long mNowUptimeMs;      public HealthStatsBatteryStatsWriter() { -        mNowRealtime = SystemClock.elapsedRealtime(); -        mNowUptime = SystemClock.uptimeMillis(); +        mNowRealtimeMs = SystemClock.elapsedRealtime(); +        mNowUptimeMs = SystemClock.uptimeMillis();      }      /** @@ -62,19 +62,20 @@ public class HealthStatsBatteryStatsWriter {          // MEASUREMENT_REALTIME_BATTERY_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS, -                bs.computeBatteryRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000); +                bs.computeBatteryRealtime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // MEASUREMENT_UPTIME_BATTERY_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS, -                bs.computeBatteryUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000); +                bs.computeBatteryUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS, -                bs.computeBatteryScreenOffRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000); +                bs.computeBatteryScreenOffRealtime( +                    mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS, -                bs.computeBatteryScreenOffUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000); +                bs.computeBatteryScreenOffUptime(mNowUptimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          //          // Now on to the real per-uid stats... @@ -214,20 +215,20 @@ public class HealthStatsBatteryStatsWriter {          // MEASUREMENT_WIFI_RUNNING_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS, -                uid.getWifiRunningTime(mNowRealtime, STATS_SINCE_UNPLUGGED)); +                uid.getWifiRunningTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // MEASUREMENT_WIFI_FULL_LOCK_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS, -                uid.getFullWifiLockTime(mNowRealtime, STATS_SINCE_UNPLUGGED)); +                uid.getFullWifiLockTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // TIMER_WIFI_SCAN          uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,                  uid.getWifiScanCount(STATS_SINCE_UNPLUGGED), -                uid.getWifiScanTime(mNowRealtime, STATS_SINCE_UNPLUGGED)); +                uid.getWifiScanTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // MEASUREMENT_WIFI_MULTICAST_MS          uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS, -                uid.getWifiMulticastTime(mNowRealtime, STATS_SINCE_UNPLUGGED)); +                uid.getWifiMulticastTime(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED)/1000);          // TIMER_AUDIO          addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer()); @@ -355,17 +356,17 @@ public class HealthStatsBatteryStatsWriter {                  uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED),                  uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED)); -        // MEASUREMENT_USER_CPU_TIME_US -        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_US, -                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED)); +        // MEASUREMENT_USER_CPU_TIME_MS +        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_MS, +                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000); -        // MEASUREMENT_SYSTEM_CPU_TIME_US -        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_US, -                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)); +        // MEASUREMENT_SYSTEM_CPU_TIME_MS +        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_MS, +                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000); -        // MEASUREMENT_CPU_POWER_MAUS -        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAUS, -                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED)); +        // MEASUREMENT_CPU_POWER_MAMS +        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, +                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED)/1000);      }      /** @@ -457,7 +458,7 @@ public class HealthStatsBatteryStatsWriter {      private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {          if (timer != null) {              writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED), -                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED)); +                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000);          }      } @@ -468,7 +469,7 @@ public class HealthStatsBatteryStatsWriter {              BatteryStats.Timer timer) {          if (timer != null) {              writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED), -                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED))); +                    timer.getTotalTimeLocked(mNowRealtimeMs*1000, STATS_SINCE_UNPLUGGED) / 1000));          }      }  } diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java index 0e192eab498f..1f3ccf530f71 100644 --- a/services/core/java/com/android/server/am/PreBootBroadcaster.java +++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java @@ -78,9 +78,12 @@ public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {          final ResolveInfo ri = mTargets.get(mIndex++);          final ComponentName componentName = ri.activityInfo.getComponentName(); -        final CharSequence label = ri.activityInfo.loadLabel(mService.mContext.getPackageManager()); -        mProgress.setProgress(mIndex, mTargets.size(), -                mService.mContext.getString(R.string.android_preparing_apk, label)); +        if (mProgress != null) { +            final CharSequence label = ri.activityInfo +                    .loadLabel(mService.mContext.getPackageManager()); +            mProgress.setProgress(mIndex, mTargets.size(), +                    mService.mContext.getString(R.string.android_preparing_apk, label)); +        }          Slog.i(TAG, "Pre-boot of " + componentName.toShortString() + " for user " + mUserId);          EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName()); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 4c050c461d9d..75d49c3ba8fc 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -101,6 +101,7 @@ import java.util.Set;   */  final class UserController {      private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; +      // Maximum number of users we allow to be running at a time.      static final int MAX_RUNNING_USERS = 3; @@ -279,7 +280,8 @@ final class UserController {                  uss.mUnlockProgress.setProgress(20);                  // Dispatch unlocked to system services -                mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0)); +                mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss.mUnlockProgress) +                        .sendToTarget();                  // Dispatch unlocked to external apps                  final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED); @@ -309,8 +311,7 @@ final class UserController {                  // Send PRE_BOOT broadcasts if fingerprint changed                  final UserInfo info = getUserInfo(userId);                  if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) { -                    uss.mUnlockProgress.startSegment(80); -                    new PreBootBroadcaster(mService, userId, uss.mUnlockProgress) { +                    new PreBootBroadcaster(mService, userId, null) {                          @Override                          public void onFinished() {                              finishUserUnlocked(uss); @@ -328,14 +329,6 @@ final class UserController {       * {@link UserState#STATE_RUNNING_UNLOCKED}.       */      private void finishUserUnlocked(UserState uss) { -        try { -            finishUserUnlockedInternal(uss); -        } finally { -            uss.mUnlockProgress.finish(); -        } -    } - -    private void finishUserUnlockedInternal(UserState uss) {          final int userId = uss.mHandle.getIdentifier();          synchronized (mService) {              // Bail if we ended up with a stale user diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java index d2f015fad881..10284bb18c75 100644 --- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java +++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java @@ -39,9 +39,9 @@ public abstract class AuthenticationClient extends ClientMonitor {      public abstract void resetFailedAttempts();      public AuthenticationClient(Context context, long halDeviceId, IBinder token, -            IFingerprintServiceReceiver receiver, int userId, int groupId, long opId, +            IFingerprintServiceReceiver receiver, int callingUserId, int groupId, long opId,              boolean restricted, String owner) { -        super(context, halDeviceId, token, receiver, userId, groupId, restricted, owner); +        super(context, halDeviceId, token, receiver, callingUserId, groupId, restricted, owner);          mOpId = opId;      } diff --git a/services/core/java/com/android/server/fingerprint/ClientMonitor.java b/services/core/java/com/android/server/fingerprint/ClientMonitor.java index 90998edd6d33..45b6d3efc4c6 100644 --- a/services/core/java/com/android/server/fingerprint/ClientMonitor.java +++ b/services/core/java/com/android/server/fingerprint/ClientMonitor.java @@ -38,7 +38,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {      protected static final boolean DEBUG = FingerprintService.DEBUG;      private IBinder mToken;      private IFingerprintServiceReceiver mReceiver; -    private int mUserId; +    private int mCallingUserId;      private int mGroupId;      private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission      private String mOwner; @@ -50,20 +50,20 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {       * @param halDeviceId the HAL device ID of the associated fingerprint hardware       * @param token a unique token for the client       * @param receiver recipient of related events (e.g. authentication) -     * @param userId userId for the fingerprint set +     * @param callingUserId user id of calling user       * @param groupId groupId for the fingerprint set       * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT}       * permission       * @param owner name of the client that owns this       */      public ClientMonitor(Context context, long halDeviceId, IBinder token, -            IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted, +            IFingerprintServiceReceiver receiver, int callingUserId, int groupId,boolean restricted,              String owner) {          mContext = context;          mHalDeviceId = halDeviceId;          mToken = token;          mReceiver = receiver; -        mUserId = userId; +        mCallingUserId = callingUserId;          mGroupId = groupId;          mIsRestricted = restricted;          mOwner = owner; @@ -197,8 +197,8 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {          return mIsRestricted;      } -    public final int getUserId() { -        return mUserId; +    public final int getCallingUserId() { +        return mCallingUserId;      }      public final int getGroupId() { diff --git a/services/core/java/com/android/server/fingerprint/EnrollClient.java b/services/core/java/com/android/server/fingerprint/EnrollClient.java index ce5b89080fb4..b636ce56e01c 100644 --- a/services/core/java/com/android/server/fingerprint/EnrollClient.java +++ b/services/core/java/com/android/server/fingerprint/EnrollClient.java @@ -46,9 +46,12 @@ public abstract class EnrollClient extends ClientMonitor {      @Override      public boolean onEnrollResult(int fingerId, int groupId, int remaining) { +        if (groupId != getGroupId()) { +            Slog.w(TAG, "groupId != getGroupId(), groupId: " + groupId + +                    " getGroupId():" + getGroupId()); +        }          if (remaining == 0) { -            FingerprintUtils.getInstance().addFingerprintForUser(getContext(), fingerId, -                    getUserId()); +            FingerprintUtils.getInstance().addFingerprintForUser(getContext(), fingerId, groupId);          }          return sendEnrollResult(fingerId, groupId, remaining);      } diff --git a/services/core/java/com/android/server/fingerprint/EnumerateClient.java b/services/core/java/com/android/server/fingerprint/EnumerateClient.java index b2e4099451ca..e826fee66da5 100644 --- a/services/core/java/com/android/server/fingerprint/EnumerateClient.java +++ b/services/core/java/com/android/server/fingerprint/EnumerateClient.java @@ -41,7 +41,7 @@ public abstract class EnumerateClient extends ClientMonitor {          try {              final int result = daemon.enumerate();              if (result != 0) { -                Slog.w(TAG, "start enumerate for user " + getUserId() +                Slog.w(TAG, "start enumerate for user " + getCallingUserId()                      + " failed, result=" + result);                  onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);                  return result; diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index c770620873e2..fcf7bf53d457 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -356,7 +356,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe          }      } -    void startRemove(IBinder token, int fingerId, int userId, int groupId, +    void startRemove(IBinder token, int fingerId, int callingUserId, int groupId,              IFingerprintServiceReceiver receiver, boolean restricted) {          IFingerprintDaemon daemon = getFingerprintDaemon();          if (daemon == null) { @@ -364,7 +364,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe              return;          }          RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token, -                receiver, userId, groupId, fingerId, restricted, token.toString()) { +                receiver, callingUserId, groupId, fingerId, restricted, token.toString()) {              @Override              public void notifyUserActivity() {                  FingerprintService.this.userActivity(); @@ -372,8 +372,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe              @Override              public IFingerprintDaemon getFingerprintDaemon() { -                FingerprintService.this.getFingerprintDaemon(); -                return null; +                return FingerprintService.this.getFingerprintDaemon();              }          };          startClient(client, true); @@ -494,7 +493,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe          }      } -    private void startAuthentication(IBinder token, long opId, int realUserId, int groupId, +    private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,                  IFingerprintServiceReceiver receiver, int flags, boolean restricted,                  String opPackageName) {          updateActiveGroup(groupId, opPackageName); @@ -502,7 +501,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe          if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");          AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token, -                receiver, realUserId, groupId, opId, restricted, opPackageName) { +                receiver, callingUserId, groupId, opId, restricted, opPackageName) {              @Override              public boolean handleFailedAttempt() {                  mFailedAttempts++; @@ -541,13 +540,13 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe          startClient(client, true /* initiatedByClient */);      } -    private void startEnrollment(IBinder token, byte [] cryptoToken, int userId, int groupId, +    private void startEnrollment(IBinder token, byte [] cryptoToken, int callingUserId, int groupId,              IFingerprintServiceReceiver receiver, int flags, boolean restricted,              String opPackageName) {          updateActiveGroup(groupId, opPackageName);          EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver, -                userId, groupId, cryptoToken, restricted, opPackageName) { +                callingUserId, groupId, cryptoToken, restricted, opPackageName) {              @Override              public IFingerprintDaemon getFingerprintDaemon() { @@ -687,9 +686,9 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe              checkPermission(MANAGE_FINGERPRINT);              final int limit =  mContext.getResources().getInteger(                      com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); -            final int callingUid = Binder.getCallingUid(); -            final int userId = UserHandle.getUserId(callingUid); -            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); +            final int callingUserId = UserHandle.getCallingUserId(); +            final int enrolled = FingerprintService.this. +                    getEnrolledFingerprints(callingUserId).size();              if (enrolled >= limit) {                  Slog.w(TAG, "Too many fingerprints registered");                  return; @@ -705,7 +704,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    startEnrollment(token, cryptoToken, userId, groupId, receiver, flags, +                    startEnrollment(token, cryptoToken, callingUserId, groupId, receiver, flags,                              restricted, opPackageName);                  }              }); @@ -735,7 +734,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe          public void authenticate(final IBinder token, final long opId, final int groupId,                  final IFingerprintServiceReceiver receiver, final int flags,                  final String opPackageName) { -            final int realUserId = Binder.getCallingUid(); +            final int callingUid = Binder.getCallingUid(); +            final int callingUserId = UserHandle.getCallingUserId();              final int pid = Binder.getCallingPid();              final boolean restricted = isRestricted();              mHandler.post(new Runnable() { @@ -743,11 +743,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe                  public void run() {                      MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);                      if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, -                            realUserId, pid)) { +                            callingUid, pid)) {                          if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);                          return;                      } -                    startAuthentication(token, opId, realUserId, groupId, receiver, +                    startAuthentication(token, opId, callingUserId, groupId, receiver,                              flags, restricted, opPackageName);                  }              }); @@ -797,11 +797,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe                  final IFingerprintServiceReceiver receiver) {              checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission              final boolean restricted = isRestricted(); -            final int realUserId = Binder.getCallingUid(); +            final int callingUserId = UserHandle.getCallingUserId();              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    startRemove(token, fingerId, realUserId, groupId, receiver, restricted); +                    startRemove(token, fingerId, callingUserId, groupId, receiver, restricted);                  }              }); diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java index 69a96e127ef7..ffa3c3f9fc83 100644 --- a/services/core/java/com/android/server/fingerprint/RemovalClient.java +++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java @@ -45,7 +45,7 @@ public abstract class RemovalClient extends ClientMonitor {          IFingerprintDaemon daemon = getFingerprintDaemon();          // The fingerprint template ids will be removed when we get confirmation from the HAL          try { -            final int result = daemon.remove(mFingerId, getUserId()); +            final int result = daemon.remove(mFingerId, getGroupId());              if (result != 0) {                  Slog.w(TAG, "startRemove with id = " + mFingerId + " failed, result=" + result);                  onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java index e97aca886c03..f67e0fdee0fb 100644 --- a/services/core/java/com/android/server/input/PersistentDataStore.java +++ b/services/core/java/com/android/server/input/PersistentDataStore.java @@ -25,6 +25,7 @@ import org.xmlpull.v1.XmlPullParser;  import org.xmlpull.v1.XmlPullParserException;  import org.xmlpull.v1.XmlSerializer; +import android.annotation.Nullable;  import android.view.Surface;  import android.hardware.input.TouchCalibration;  import android.text.TextUtils; @@ -342,6 +343,7 @@ final class PersistentDataStore {                  "x_ymix", "x_offset", "y_xmix", "y_scale", "y_offset" };          private TouchCalibration[] mTouchCalibration = new TouchCalibration[4]; +        @Nullable          private String mCurrentKeyboardLayout;          private List<String> mUnassociatedKeyboardLayouts = new ArrayList<>();          private ArrayMap<InputMethodSubtypeHandle, String> mKeyboardLayouts = new ArrayMap<>(); @@ -368,6 +370,7 @@ final class PersistentDataStore {              }          } +        @Nullable          public String getCurrentKeyboardLayout() {              return mCurrentKeyboardLayout;          } @@ -443,7 +446,7 @@ final class PersistentDataStore {          public boolean switchKeyboardLayout(InputMethodSubtypeHandle imeHandle) {              final String layout = mKeyboardLayouts.get(imeHandle); -            if (layout != null && !TextUtils.equals(mCurrentKeyboardLayout, layout)) { +            if (!TextUtils.equals(mCurrentKeyboardLayout, layout)) {                  mCurrentKeyboardLayout = layout;                  return true;              } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 43250ba9271d..063362500a72 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -216,6 +216,7 @@ import android.util.SparseArray;  import android.util.SparseBooleanArray;  import android.util.SparseIntArray;  import android.util.Xml; +import android.util.jar.StrictJarFile;  import android.view.Display;  import com.android.internal.R; @@ -7643,6 +7644,52 @@ public class PackageManagerService extends IPackageManager.Stub {          }      } +    /** +     * Returns {@code true} if the given file contains code. Otherwise {@code false}. +     */ +    private static boolean apkHasCode(String fileName) { +        StrictJarFile jarFile = null; +        try { +            jarFile = new StrictJarFile(fileName, +                    false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/); +            return jarFile.findEntry("classes.dex") != null; +        } catch (IOException ignore) { +        } finally { +            try { +                jarFile.close(); +            } catch (IOException ignore) {} +        } +        return false; +    } + +    /** +     * Enforces code policy for the package. This ensures that if an APK has +     * declared hasCode="true" in its manifest that the APK actually contains +     * code. +     * +     * @throws PackageManagerException If bytecode could not be found when it should exist +     */ +    private static void enforceCodePolicy(PackageParser.Package pkg) +            throws PackageManagerException { +        final boolean shouldHaveCode = +                (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; +        if (shouldHaveCode && !apkHasCode(pkg.baseCodePath)) { +            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, +                    "Package " + pkg.baseCodePath + " code is missing"); +        } + +        if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { +            for (int i = 0; i < pkg.splitCodePaths.length; i++) { +                final boolean splitShouldHaveCode = +                        (pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; +                if (splitShouldHaveCode && !apkHasCode(pkg.splitCodePaths[i])) { +                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, +                            "Package " + pkg.splitCodePaths[i] + " code is missing"); +                } +            } +        } +    } +      private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,              final int policyFlags, final int scanFlags, long currentTime, UserHandle user)              throws PackageManagerException { @@ -7687,6 +7734,10 @@ public class PackageManagerService extends IPackageManager.Stub {              pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;          } +        if ((policyFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) { +            enforceCodePolicy(pkg); +        } +          if (mCustomResolverComponentName != null &&                  mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {              setUpCustomResolverActivity(pkg); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 42f7166fb7ca..93e4d313cce2 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -667,6 +667,8 @@ public class UserManagerService extends IUserManager.Stub {              long identity = Binder.clearCallingIdentity();              try {                  if (enableQuietMode) { +                    LocalServices.getService(ActivityManagerInternal.class) +                            .killForegroundAppsForUser(userHandle);                      ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);                  } else {                      ActivityManagerNative.getDefault().startUserInBackground(userHandle); @@ -2359,11 +2361,13 @@ public class UserManagerService extends IUserManager.Stub {      public void setApplicationRestrictions(String packageName, Bundle restrictions,              int userId) {          checkSystemOrRoot("set application restrictions"); +        if (restrictions != null) { +            restrictions.setDefusable(true); +        }          synchronized (mPackagesLock) {              if (restrictions == null || restrictions.isEmpty()) {                  cleanAppRestrictionsForPackage(packageName, userId);              } else { -                restrictions.setDefusable(true);                  // Write the restrictions to XML                  writeApplicationRestrictionsLP(packageName, restrictions, userId);              } diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java index 0c80ffa55716..5878709e89b1 100644 --- a/services/core/java/com/android/server/policy/BarController.java +++ b/services/core/java/com/android/server/policy/BarController.java @@ -18,15 +18,14 @@ package com.android.server.policy;  import android.app.StatusBarManager;  import android.os.Handler; -import android.os.RemoteException; -import android.os.ServiceManager;  import android.os.SystemClock;  import android.util.Slog;  import android.view.View;  import android.view.WindowManager;  import android.view.WindowManagerPolicy.WindowState; -import com.android.internal.statusbar.IStatusBarService; +import com.android.server.LocalServices; +import com.android.server.statusbar.StatusBarManagerInternal;  import java.io.PrintWriter; @@ -52,7 +51,7 @@ public class BarController {      private final int mTranslucentWmFlag;      protected final Handler mHandler;      private final Object mServiceAquireLock = new Object(); -    protected IStatusBarService mStatusBarService; +    protected StatusBarManagerInternal mStatusBarInternal;      private WindowState mWin;      private int mState = StatusBarManager.WINDOW_STATE_SHOWING; @@ -182,15 +181,9 @@ public class BarController {              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    try { -                        IStatusBarService statusbar = getStatusBarService(); -                        if (statusbar != null) { -                            statusbar.setWindowState(mStatusBarManagerId, state); -                        } -                    } catch (RemoteException e) { -                        if (DEBUG) Slog.w(mTag, "Error posting window state", e); -                        // re-acquire status bar service next time it is needed. -                        mStatusBarService = null; +                    StatusBarManagerInternal statusbar = getStatusBarInternal(); +                    if (statusbar != null) { +                        statusbar.setWindowState(mStatusBarManagerId, state);                      }                  }              }); @@ -276,13 +269,12 @@ public class BarController {          }      } -    protected IStatusBarService getStatusBarService() { +    protected StatusBarManagerInternal getStatusBarInternal() {          synchronized (mServiceAquireLock) { -            if (mStatusBarService == null) { -                mStatusBarService = IStatusBarService.Stub.asInterface( -                        ServiceManager.getService("statusbar")); +            if (mStatusBarInternal == null) { +                mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);              } -            return mStatusBarService; +            return mStatusBarInternal;          }      } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1686f14b5852..007190dff3f8 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1467,14 +1467,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {      private void requestTvPictureInPictureInternal() {          try { -            IStatusBarService statusbar = getStatusBarService(); +            StatusBarManagerInternal statusbar = getStatusBarManagerInternal();              if (statusbar != null) {                  statusbar.requestTvPictureInPicture();              } -        } catch (RemoteException|IllegalArgumentException e) { +        } catch (IllegalArgumentException e) {              Slog.e(TAG, "Cannot handle picture-in-picture key", e); -            // re-acquire status bar service next time it is needed. -            mStatusBarService = null;          }      } @@ -3562,21 +3560,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {              ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))                      .launchLegacyAssist(hint, UserHandle.myUserId(), args);          } else { -            try { -                if (hint != null) { -                    if (args == null) { -                        args = new Bundle(); -                    } -                    args.putBoolean(hint, true); -                } -                IStatusBarService statusbar = getStatusBarService(); -                if (statusbar != null) { -                    statusbar.startAssist(args); +            if (hint != null) { +                if (args == null) { +                    args = new Bundle();                  } -            } catch (RemoteException e) { -                Slog.e(TAG, "RemoteException when starting assist", e); -                // re-acquire status bar service next time it is needed. -                mStatusBarService = null; +                args.putBoolean(hint, true); +            } +            StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +            if (statusbar != null) { +                statusbar.startAssist(args);              }          }      } @@ -3598,45 +3590,27 @@ public class PhoneWindowManager implements WindowManagerPolicy {      private void preloadRecentApps() {          mPreloadedRecentApps = true; -        try { -            IStatusBarService statusbar = getStatusBarService(); -            if (statusbar != null) { -                statusbar.preloadRecentApps(); -            } -        } catch (RemoteException e) { -            Slog.e(TAG, "RemoteException when preloading recent apps", e); -            // re-acquire status bar service next time it is needed. -            mStatusBarService = null; +        StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +        if (statusbar != null) { +            statusbar.preloadRecentApps();          }      }      private void cancelPreloadRecentApps() {          if (mPreloadedRecentApps) {              mPreloadedRecentApps = false; -            try { -                IStatusBarService statusbar = getStatusBarService(); -                if (statusbar != null) { -                    statusbar.cancelPreloadRecentApps(); -                } -            } catch (RemoteException e) { -                Slog.e(TAG, "RemoteException when cancelling recent apps preload", e); -                // re-acquire status bar service next time it is needed. -                mStatusBarService = null; +            StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +            if (statusbar != null) { +                statusbar.cancelPreloadRecentApps();              }          }      }      private void toggleRecentApps() {          mPreloadedRecentApps = false; // preloading no longer needs to be canceled -        try { -            IStatusBarService statusbar = getStatusBarService(); -            if (statusbar != null) { -                statusbar.toggleRecentApps(); -            } -        } catch (RemoteException e) { -            Slog.e(TAG, "RemoteException when toggling recent apps", e); -            // re-acquire status bar service next time it is needed. -            mStatusBarService = null; +        StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +        if (statusbar != null) { +            statusbar.toggleRecentApps();          }      } @@ -3648,40 +3622,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {      private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {          mPreloadedRecentApps = false; // preloading no longer needs to be canceled -        try { -            IStatusBarService statusbar = getStatusBarService(); -            if (statusbar != null) { -                statusbar.showRecentApps(triggeredFromAltTab, fromHome); -            } -        } catch (RemoteException e) { -            Slog.e(TAG, "RemoteException when showing recent apps", e); -            // re-acquire status bar service next time it is needed. -            mStatusBarService = null; +        StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +        if (statusbar != null) { +            statusbar.showRecentApps(triggeredFromAltTab, fromHome);          }      }      private void toggleKeyboardShortcutsMenu(int deviceId) { -        try { -            IStatusBarService statusbar = getStatusBarService(); -            if (statusbar != null) { -                statusbar.toggleKeyboardShortcutsMenu(deviceId); -            } -        } catch (RemoteException e) { -            Slog.e(TAG, "RemoteException when showing keyboard shortcuts menu", e); +        StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +        if (statusbar != null) { +            statusbar.toggleKeyboardShortcutsMenu(deviceId);          }      }      private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) {          mPreloadedRecentApps = false; // preloading no longer needs to be canceled -        try { -            IStatusBarService statusbar = getStatusBarService(); -            if (statusbar != null) { -                statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); -            } -        } catch (RemoteException e) { -            Slog.e(TAG, "RemoteException when closing recent apps", e); -            // re-acquire status bar service next time it is needed. -            mStatusBarService = null; +        StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); +        if (statusbar != null) { +            statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome);          }      } @@ -7483,13 +7441,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {          if (mKeyguardDelegate != null) {              mKeyguardDelegate.setCurrentUser(newUserId);          } -        IStatusBarService statusBar = getStatusBarService(); +        StatusBarManagerInternal statusBar = getStatusBarManagerInternal();          if (statusBar != null) { -            try { -                statusBar.setCurrentUser(newUserId); -            } catch (RemoteException e) { -                // oh well -            } +            statusBar.setCurrentUser(newUserId);          }          setLastInputMethodWindowLw(null, null);      } diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java index 86d046829727..245518ca28f6 100644 --- a/services/core/java/com/android/server/policy/StatusBarController.java +++ b/services/core/java/com/android/server/policy/StatusBarController.java @@ -18,9 +18,7 @@ package com.android.server.policy;  import android.app.StatusBarManager;  import android.os.IBinder; -import android.os.RemoteException;  import android.os.SystemClock; -import android.util.Slog;  import android.view.View;  import android.view.WindowManager;  import android.view.animation.Animation; @@ -28,7 +26,6 @@ import android.view.animation.AnimationSet;  import android.view.animation.Interpolator;  import android.view.animation.TranslateAnimation; -import com.android.internal.statusbar.IStatusBarService;  import com.android.server.LocalServices;  import com.android.server.statusbar.StatusBarManagerInternal; @@ -49,15 +46,9 @@ public class StatusBarController extends BarController {              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    try { -                        IStatusBarService statusbar = getStatusBarService(); -                        if (statusbar != null) { -                            statusbar.appTransitionPending(); -                        } -                    } catch (RemoteException e) { -                        Slog.e(mTag, "RemoteException when app transition is pending", e); -                        // re-acquire status bar service next time it is needed. -                        mStatusBarService = null; +                    StatusBarManagerInternal statusbar = getStatusBarInternal(); +                    if (statusbar != null) { +                        statusbar.appTransitionPending();                      }                  }              }); @@ -69,19 +60,13 @@ public class StatusBarController extends BarController {              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    try { -                        IStatusBarService statusbar = getStatusBarService(); -                        if (statusbar != null) { -                            long startTime = calculateStatusBarTransitionStartTime(openAnimation, -                                    closeAnimation); -                            long duration = closeAnimation != null || openAnimation != null -                                    ? TRANSITION_DURATION : 0; -                            statusbar.appTransitionStarting(startTime, duration); -                        } -                    } catch (RemoteException e) { -                        Slog.e(mTag, "RemoteException when app transition is starting", e); -                        // re-acquire status bar service next time it is needed. -                        mStatusBarService = null; +                    StatusBarManagerInternal statusbar = getStatusBarInternal(); +                    if (statusbar != null) { +                        long startTime = calculateStatusBarTransitionStartTime(openAnimation, +                                closeAnimation); +                        long duration = closeAnimation != null || openAnimation != null +                                ? TRANSITION_DURATION : 0; +                        statusbar.appTransitionStarting(startTime, duration);                      }                  }              }); @@ -92,15 +77,9 @@ public class StatusBarController extends BarController {              mHandler.post(new Runnable() {                  @Override                  public void run() { -                    try { -                        IStatusBarService statusbar = getStatusBarService(); -                        if (statusbar != null) { -                            statusbar.appTransitionCancelled(); -                        } -                    } catch (RemoteException e) { -                        Slog.e(mTag, "RemoteException when app transition is cancelled", e); -                        // re-acquire status bar service next time it is needed. -                        mStatusBarService = null; +                    StatusBarManagerInternal statusbar = getStatusBarInternal(); +                    if (statusbar != null) { +                        statusbar.appTransitionCancelled();                      }                  }              }); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 95923fe159a2..38a3d01988f8 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -28,6 +28,50 @@ public interface StatusBarManagerInternal {      void notificationLightOff();      void showScreenPinningRequest(int taskId);      void showAssistDisclosure(); + +    void preloadRecentApps(); + +    void cancelPreloadRecentApps(); + +    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome); + +    void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey); + +    void toggleKeyboardShortcutsMenu(int deviceId); + +    /** +     * Request picture-in-picture. +     * +     * <p> +     * This is called when an user presses picture-in-picture key or equivalent. +     * TV device may start picture-in-picture from foreground activity if there's none. +     * Picture-in-picture overlay menu will be shown instead otherwise. +     */ +    void requestTvPictureInPicture(); + +    void setWindowState(int window, int state); + +    /** +     * Notifies the status bar that an app transition is pending to delay applying some flags with +     * visual impact until {@link #appTransitionReady} is called. +     */ +    void appTransitionPending(); + +    /** +     * Notifies the status bar that a pending app transition has been cancelled. +     */ +    void appTransitionCancelled(); + +    /** +     * Notifies the status bar that an app transition is now being executed. +     * +     * @param statusBarAnimationsStartTime the desired start time for all visual animations in the +     *        status bar caused by this app transition in uptime millis +     * @param statusBarAnimationsDuration the duration for all visual animations in the status +     *        bar caused by this app transition in millis +     */ +    void appTransitionStarting(long statusBarAnimationsStartTime, long statusBarAnimationsDuration); +      void startAssist(Bundle args);      void onCameraLaunchGestureDetected(int source);      void topAppWindowChanged(boolean menuVisible); @@ -35,4 +79,8 @@ public interface StatusBarManagerInternal {              Rect fullscreenBounds, Rect dockedBounds, String cause);      void toggleSplitScreen();      void appTransitionFinished(); + +    void toggleRecentApps(); + +    void setCurrentUser(int newUserId);  } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 981b75aa2ee0..902067732fb2 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -223,6 +223,114 @@ public class StatusBarManagerService extends IStatusBarService.Stub {                  } catch (RemoteException ex) {}              }          } + +        @Override +        public void toggleRecentApps() { +            if (mBar != null) { +                try { +                    mBar.toggleRecentApps(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void setCurrentUser(int newUserId) { +            if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId); +            mCurrentUserId = newUserId; +        } + + +        @Override +        public void preloadRecentApps() { +            if (mBar != null) { +                try { +                    mBar.preloadRecentApps(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void cancelPreloadRecentApps() { +            if (mBar != null) { +                try { +                    mBar.cancelPreloadRecentApps(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { +            if (mBar != null) { +                try { +                    mBar.showRecentApps(triggeredFromAltTab, fromHome); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { +            if (mBar != null) { +                try { +                    mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void toggleKeyboardShortcutsMenu(int deviceId) { +            if (mBar != null) { +                try { +                    mBar.toggleKeyboardShortcutsMenu(deviceId); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void requestTvPictureInPicture() { +            if (mBar != null) { +                try { +                    mBar.requestTvPictureInPicture(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void setWindowState(int window, int state) { +            if (mBar != null) { +                try { +                    mBar.setWindowState(window, state); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void appTransitionPending() { +            if (mBar != null) { +                try { +                    mBar.appTransitionPending(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void appTransitionCancelled() { +            if (mBar != null) { +                try { +                    mBar.appTransitionCancelled(); +                } catch (RemoteException ex) {} +            } +        } + +        @Override +        public void appTransitionStarting(long statusBarAnimationsStartTime, +                long statusBarAnimationsDuration) { +            if (mBar != null) { +                try { +                    mBar.appTransitionStarting( +                            statusBarAnimationsStartTime, statusBarAnimationsDuration); +                } catch (RemoteException ex) {} +            } +        }      };      // ================================================================================ @@ -527,122 +635,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub {          }      } -    @Override -    public void toggleRecentApps() { -        if (mBar != null) { -            try { -                mBar.toggleRecentApps(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void preloadRecentApps() { -        if (mBar != null) { -            try { -                mBar.preloadRecentApps(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void cancelPreloadRecentApps() { -        if (mBar != null) { -            try { -                mBar.cancelPreloadRecentApps(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { -        if (mBar != null) { -            try { -                mBar.showRecentApps(triggeredFromAltTab, fromHome); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { -        if (mBar != null) { -            try { -                mBar.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void toggleKeyboardShortcutsMenu(int deviceId) { -        if (mBar != null) { -            try { -                mBar.toggleKeyboardShortcutsMenu(deviceId); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void requestTvPictureInPicture() { -        if (mBar != null) { -            try { -                mBar.requestTvPictureInPicture(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void setCurrentUser(int newUserId) { -        if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId); -        mCurrentUserId = newUserId; -    } - -    @Override -    public void setWindowState(int window, int state) { -        if (mBar != null) { -            try { -                mBar.setWindowState(window, state); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void appTransitionPending() { -        if (mBar != null) { -            try { -                mBar.appTransitionPending(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void appTransitionCancelled() { -        if (mBar != null) { -            try { -                mBar.appTransitionCancelled(); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void appTransitionStarting(long statusBarAnimationsStartTime, -            long statusBarAnimationsDuration) { -        if (mBar != null) { -            try { -                mBar.appTransitionStarting( -                        statusBarAnimationsStartTime, statusBarAnimationsDuration); -            } catch (RemoteException ex) {} -        } -    } - -    @Override -    public void startAssist(Bundle args) { -        if (mBar != null) { -            try { -                mBar.startAssist(args); -            } catch (RemoteException ex) {} -        } -    } -      private void enforceStatusBarOrShell() {          if (Binder.getCallingUid() == Process.SHELL_UID) {              return; diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index b7d6062a3dc0..eacdd811592b 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -129,13 +129,16 @@ public class BoundsAnimationController {          public void onAnimationStart(Animator animation) {              if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget                      + " mReplacement=" + mReplacement); -            if (animatingToLargerSize()) { -                mTarget.setPinnedStackSize(mFrom, mTo); -            } -              if (!mReplacement) {                  mTarget.onAnimationStart();              } + +            // Ensure that we have prepared the target for animation before +            // we trigger any size changes, so it can swap surfaces +            // in to appropriate modes, or do as it wishes otherwise. +            if (animatingToLargerSize()) { +                mTarget.setPinnedStackSize(mFrom, mTo); +            }          }          @Override diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 0039c0a4b02a..b90d0d191a78 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -663,4 +663,8 @@ public class DockedStackDividerController implements DimLayerUser {      public String toShortString() {          return TAG;      } -}
\ No newline at end of file + +    WindowState getWindow() { +        return mWindow; +    } +} diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 46a8dffc02e6..4f49eed14090 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -600,7 +600,8 @@ class Task implements DimLayer.DimLayerUser {                      //                      // Anyway we don't need to synchronize position and content updates for these                      // windows since they aren't at the base layer and could be moved around anyway. -                    if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION) { +                    if (!win.computeDragResizing() && win.mAttrs.type == TYPE_BASE_APPLICATION && +                            !mStack.getBoundsAnimating()) {                          win.mResizedWhileNotDragResizing = true;                      }                  } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 872bc6d5bc9f..1fd2b1f2dfa3 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -42,6 +42,7 @@ import android.util.SparseArray;  import android.view.DisplayInfo;  import android.view.Surface;  import android.view.animation.PathInterpolator; +import android.view.SurfaceControl;  import com.android.internal.policy.DividerSnapAlgorithm;  import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget; @@ -127,10 +128,12 @@ public class TaskStack implements DimLayer.DimLayerUser,      private float mAdjustImeAmount;      private final int mDockedStackMinimizeThickness; -    // If this is true, the task will be down or upscaled -    // to perfectly fit the region it would have been cropped -    // to. -    private boolean mForceScaleToCrop = false; +    // If this is true, we are in the bounds animating mode. +    // The task will be down or upscaled to perfectly fit the +    // region it would have been cropped to. We may also avoid +    // certain logic we would otherwise apply while resizing, +    // while resizing in the bounds animating mode. +    private boolean mBoundsAnimating = false;      // By default, movement animations are applied to all      // window movement. If this is true, animations will not      // be applied within this stack. This is useful for example @@ -1269,11 +1272,36 @@ public class TaskStack implements DimLayer.DimLayerUser,          return true;      } +    void forceWindowsScaleable(boolean force) { +        SurfaceControl.openTransaction(); +        try { +            for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { +                final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens; +                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { +                    final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows; +                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { +                        final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator; +                        if (winAnimator == null || !winAnimator.hasSurface()) { +                            continue; +                        } +                        winAnimator.mSurfaceController.forceScaleableInTransaction(force); +                    } +                } +            } +        } finally { +            SurfaceControl.closeTransaction(); +        } +    } +      @Override  // AnimatesBounds      public void onAnimationStart() {          synchronized (mService.mWindowMap) { +            // We force windows out of SCALING_MODE_FREEZE +            // so that we can continue to animate them +            // while a resize is pending. +            forceWindowsScaleable(true);              mFreezeMovementAnimations = true; -            mForceScaleToCrop = true; +            mBoundsAnimating = true;          }      } @@ -1281,7 +1309,8 @@ public class TaskStack implements DimLayer.DimLayerUser,      public void onAnimationEnd() {          synchronized (mService.mWindowMap) {              mFreezeMovementAnimations = false; -            mForceScaleToCrop = false; +            mBoundsAnimating = false; +            forceWindowsScaleable(false);              mService.requestTraversal();          }          if (mStackId == PINNED_STACK_ID) { @@ -1312,6 +1341,10 @@ public class TaskStack implements DimLayer.DimLayerUser,      }      public boolean getForceScaleToCrop() { -        return mForceScaleToCrop; +        return mBoundsAnimating; +    } + +    public boolean getBoundsAnimating() { +        return mBoundsAnimating;      }  } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 79ff78e8496e..38f12a13e379 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1563,6 +1563,16 @@ public class WindowManagerService extends IWindowManager.Stub                      mLayersController.setInputMethodAnimLayerAdjustment(0);                  }              } + +            // If the docked divider is visible, we still need to go through this whole +            // excercise to find the appropriate input method target (used for animations +            // and dialog adjustments), but for purposes of Z ordering we simply wish to +            // place it above the docked divider. +            WindowState dockedDivider = w.mDisplayContent.mDividerControllerLocked.getWindow(); +            if (dockedDivider != null && dockedDivider.isVisibleLw()) { +                int dividerIndex = windows.indexOf(dockedDivider); +                return dividerIndex > 0 ? dividerIndex + 1 : i + 1; +            }              return i+1;          }          if (willMove) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 5077f3293808..76fdda0175f0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2382,6 +2382,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {                  if (stack != null) {                      pw.print(" stackId="); pw.print(stack.mStackId);                  } +                if (mNotOnAppsDisplay) { +                    pw.print(" mNotOnAppsDisplay="); pw.print(mNotOnAppsDisplay); +                }                  pw.print(" mSession="); pw.print(mSession);                  pw.print(" mClient="); pw.println(mClient.asBinder());          pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 1f76f318b251..8c29c9b194ad 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -562,6 +562,7 @@ class WindowStateAnimator {              Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="                      + drawStateToString());          } +          if (mWin.mAppToken != null && mWin.mAppToken.mAnimatingWithSavedSurface) {              // App has drawn something to its windows, we're no longer animating with              // the saved surfaces. If the user exits now, we only want to save again @@ -1290,6 +1291,17 @@ class WindowStateAnimator {      }      private void adjustCropToStackBounds(WindowState w, Rect clipRect, Rect finalClipRect,              boolean isFreeformResizing) { + +        final DisplayContent displayContent = w.getDisplayContent(); +        if (displayContent != null && !displayContent.isDefaultDisplay) { +            // There are some windows that live on other displays while their app and main window +            // live on the default display (e.g. casting...). We don't want to crop this windows +            // to the stack bounds which is only currently supported on the default display. +            // TODO(multi-display): Need to support cropping to stack bounds on other displays +            // when we have stacks on other displays. +            return; +        } +          final Task task = w.getTask();          if (task == null || !task.cropWindowsToStackBounds()) {              return; @@ -1352,7 +1364,7 @@ class WindowStateAnimator {          final Task task = w.getTask();          // We got resized, so block all updates until we got the new surface. -        if (w.mResizedWhileNotDragResizing) { +        if (w.mResizedWhileNotDragResizing && !w.isGoneForLayoutLw()) {              return;          } diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 8799c614cf25..6eed5e746458 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -23,6 +23,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE  import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;  import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;  import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static android.view.Surface.SCALING_MODE_FREEZE; +import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;  import android.graphics.Point;  import android.graphics.PointF; @@ -392,6 +394,13 @@ class WindowSurfaceController {          mSurfaceControl.deferTransactionUntil(handle, frame);      } +    void forceScaleableInTransaction(boolean force) { +        // -1 means we don't override the default or client specified +        // scaling mode. +        int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1; +        mSurfaceControl.setOverrideScalingMode(scalingMode); +    } +      boolean clearWindowContentFrameStats() {          if (mSurfaceControl == null) {              return false; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index d3d05f3ca36a..45a73118320c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2909,6 +2909,54 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {          }      } +    public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) { +        if (!mHasFeature) { +            return; +        } +        Preconditions.checkNotNull(adminReceiver, "ComponentName is null"); +        enforceShell("forceRemoveActiveAdmin"); +        long ident = mInjector.binderClearCallingIdentity(); +        try { +            final ApplicationInfo ai; +            try { +                ai = mIPackageManager.getApplicationInfo(adminReceiver.getPackageName(), +                        0, userHandle); +            } catch (RemoteException e) { +                throw new IllegalStateException(e); +            } +            if (ai == null) { +                throw new IllegalStateException("Couldn't find package to remove admin " +                        + adminReceiver.getPackageName() + " " + userHandle); +            } +            if ((ai.flags & ApplicationInfo.FLAG_TEST_ONLY) == 0) { +                throw new SecurityException("Attempt to remove non-test admin " + adminReceiver +                        + adminReceiver + " " + userHandle); +            } +            // If admin is a device or profile owner tidy that up first. +            synchronized (this)  { +                if (isDeviceOwner(adminReceiver, userHandle)) { +                    clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle); +                } +                if (isProfileOwner(adminReceiver, userHandle)) { +                    final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, +                            userHandle, /* parent */ false); +                    clearProfileOwnerLocked(admin, userHandle); +                } +            } +            // Remove the admin skipping sending the broadcast. +            removeAdminArtifacts(adminReceiver, userHandle); +        } finally { +            mInjector.binderRestoreCallingIdentity(ident); +        } +    } + +    private void enforceShell(String method) { +        final int callingUid = Binder.getCallingUid(); +        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) { +            throw new SecurityException("Non-shell user attempted to call " + method); +        } +    } +      @Override      public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {          if (!mHasFeature) { @@ -5732,32 +5780,37 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {              enforceUserUnlocked(deviceOwnerUserId);              final ActiveAdmin admin = getDeviceOwnerAdminLocked(); -            if (admin != null) { -                admin.disableCamera = false; -                admin.userRestrictions = null; -                admin.forceEphemeralUsers = false; -                mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers); -            } -            clearUserPoliciesLocked(deviceOwnerUserId); - -            mOwners.clearDeviceOwner(); -            mOwners.writeDeviceOwner(); -            updateDeviceOwnerLocked(); -            disableSecurityLoggingIfNotCompliant(); -            // Reactivate backup service.              long ident = mInjector.binderClearCallingIdentity();              try { -                mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true); - +                clearDeviceOwnerLocked(admin, deviceOwnerUserId);                  removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId); -            } catch (RemoteException e) { -                throw new IllegalStateException("Failed reactivating backup service.", e);              } finally {                  mInjector.binderRestoreCallingIdentity(ident);              }          }      } +    private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) { +        if (admin != null) { +            admin.disableCamera = false; +            admin.userRestrictions = null; +            admin.forceEphemeralUsers = false; +            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers); +        } +        clearUserPoliciesLocked(userId); + +        mOwners.clearDeviceOwner(); +        mOwners.writeDeviceOwner(); +        updateDeviceOwnerLocked(); +        disableSecurityLoggingIfNotCompliant(); +        try { +            // Reactivate backup service. +            mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true); +        } catch (RemoteException e) { +            throw new IllegalStateException("Failed reactivating backup service.", e); +        } +    } +      @Override      public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {          if (!mHasFeature) { @@ -5794,14 +5847,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {          final ActiveAdmin admin =                  getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);          synchronized (this) { -            admin.disableCamera = false; -            admin.userRestrictions = null; -            clearUserPoliciesLocked(userId); -            mOwners.removeProfileOwner(userId); -            mOwners.writeProfileOwner(userId); -              final long ident = mInjector.binderClearCallingIdentity();              try { +                clearProfileOwnerLocked(admin, userId);                  removeActiveAdminLocked(who, userId);              } finally {                  mInjector.binderRestoreCallingIdentity(ident); @@ -5809,6 +5857,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {          }      } +    public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) { +        if (admin != null) { +            admin.disableCamera = false; +            admin.userRestrictions = null; +        } +        clearUserPoliciesLocked(userId); +        mOwners.removeProfileOwner(userId); +        mOwners.writeProfileOwner(userId); +    } +      @Override      public void setDeviceOwnerLockScreenInfo(ComponentName who, CharSequence info) {          Preconditions.checkNotNull(who, "ComponentName is null"); @@ -5842,15 +5900,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {          policy.mUserProvisioningState = DevicePolicyManager.STATE_USER_UNMANAGED;          saveSettingsLocked(userId); -        final long ident = mInjector.binderClearCallingIdentity();          try {              mIPackageManager.updatePermissionFlagsForAllApps(                      PackageManager.FLAG_PERMISSION_POLICY_FIXED,                      0  /* flagValues */, userId);              pushUserRestrictions(userId);          } catch (RemoteException re) { -        } finally { -            mInjector.binderRestoreCallingIdentity(ident); +            // Shouldn't happen.          }      } diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java index c6d5a7e268b7..723be2481d6f 100644 --- a/services/midi/java/com/android/server/midi/MidiService.java +++ b/services/midi/java/com/android/server/midi/MidiService.java @@ -126,8 +126,8 @@ public class MidiService extends IMidiManager.Stub {          // This client's PID          private final int mPid;          // List of all receivers for this client -        private final ArrayList<IMidiDeviceListener> mListeners -                = new ArrayList<IMidiDeviceListener>(); +        private final HashMap<IBinder, IMidiDeviceListener> mListeners +                = new HashMap<IBinder, IMidiDeviceListener>();          // List of all device connections for this client          private final HashMap<IBinder, DeviceConnection> mDeviceConnections                  = new HashMap<IBinder, DeviceConnection>(); @@ -143,11 +143,13 @@ public class MidiService extends IMidiManager.Stub {          }          public void addListener(IMidiDeviceListener listener) { -            mListeners.add(listener); +            // Use asBinder() so that we can match it in removeListener(). +            // The listener proxy objects themselves do not match. +            mListeners.put(listener.asBinder(), listener);          }          public void removeListener(IMidiDeviceListener listener) { -            mListeners.remove(listener); +            mListeners.remove(listener.asBinder());              if (mListeners.size() == 0 && mDeviceConnections.size() == 0) {                  close();              } @@ -184,7 +186,7 @@ public class MidiService extends IMidiManager.Stub {              MidiDeviceInfo deviceInfo = device.getDeviceInfo();              try { -                for (IMidiDeviceListener listener : mListeners) { +                for (IMidiDeviceListener listener : mListeners.values()) {                      listener.onDeviceAdded(deviceInfo);                  }              } catch (RemoteException e) { @@ -198,7 +200,7 @@ public class MidiService extends IMidiManager.Stub {              MidiDeviceInfo deviceInfo = device.getDeviceInfo();              try { -                for (IMidiDeviceListener listener : mListeners) { +                for (IMidiDeviceListener listener : mListeners.values()) {                      listener.onDeviceRemoved(deviceInfo);                  }              } catch (RemoteException e) { @@ -211,7 +213,7 @@ public class MidiService extends IMidiManager.Stub {              if (!device.isUidAllowed(mUid)) return;              try { -                for (IMidiDeviceListener listener : mListeners) { +                for (IMidiDeviceListener listener : mListeners.values()) {                      listener.onDeviceStatusChanged(status);                  }              } catch (RemoteException e) { diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk index 7ffdb35bc277..59c6970d1feb 100644 --- a/services/tests/servicestests/Android.mk +++ b/services/tests/servicestests/Android.mk @@ -28,10 +28,22 @@ LOCAL_PACKAGE_NAME := FrameworksServicesTests  LOCAL_CERTIFICATE := platform -LOCAL_JNI_SHARED_LIBRARIES := \ -    libapfjni \ +# These are not normally accessible from apps so they must be explicitly included. +LOCAL_JNI_SHARED_LIBRARIES := libservicestestsjni \ +    libbacktrace \ +    libbase \ +    libbinder \      libc++ \ -    libnativehelper +    libcutils \ +    liblog \ +    liblzma \ +    libnativehelper \ +    libnetdaidl \ +    libui \ +    libunwind \ +    libutils + +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk  include $(BUILD_PACKAGE) @@ -45,22 +57,24 @@ include $(CLEAR_VARS)  LOCAL_MODULE_TAGS := tests -LOCAL_CFLAGS := -Wall -Werror +LOCAL_CFLAGS := -Wall -Wextra -Werror  LOCAL_C_INCLUDES := \    libpcap \    hardware/google/apf -LOCAL_SRC_FILES := apf_jni.cpp +LOCAL_SRC_FILES := $(call all-cpp-files-under)  LOCAL_SHARED_LIBRARIES := \ +  libbinder \ +  libcutils \    libnativehelper \ -  liblog +  libnetdaidl  LOCAL_STATIC_LIBRARIES := \    libpcap \    libapf -LOCAL_MODULE := libapfjni +LOCAL_MODULE := libservicestestsjni  include $(BUILD_SHARED_LIBRARY) diff --git a/services/tests/servicestests/jni/UidRangeTest.cpp b/services/tests/servicestests/jni/UidRangeTest.cpp new file mode 100644 index 000000000000..7941731a07f3 --- /dev/null +++ b/services/tests/servicestests/jni/UidRangeTest.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <memory> + +#include <binder/Parcel.h> + +#include "UidRangeTest.h" + +using android::net::UidRange; + +extern "C" +JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass, +        jbyteArray inParcel) { +    const UidRange range = unmarshall(env, inParcel); +    return marshall(env, range); +} + +extern "C" +JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel) { +    const UidRange range = unmarshall(env, inParcel); +    return range.getStart(); +} + +extern "C" +JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel) { +    const UidRange range = unmarshall(env, inParcel); +    return range.getStop(); +} + + +/** + * Reads exactly one UidRange from 'parcelData' assuming that it is a Parcel. Any bytes afterward + * are ignored. + */ +UidRange unmarshall(JNIEnv* env, jbyteArray parcelData) { +    const int length = env->GetArrayLength(parcelData); + +    std::unique_ptr<uint8_t> bytes(new uint8_t[length]); +    env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get())); + +    android::Parcel p; +    p.setData(bytes.get(), length); + +    UidRange range; +    range.readFromParcel(&p); +    return range; +} + +/** + * Creates a Java byte[] array and writes the contents of 'range' to it as a Parcel containing + * exactly one object. + * + * Every UidRange maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and + * 'unmarshall(e, marshall(e, x))' should be fixed points. + */ +jbyteArray marshall(JNIEnv* env, const UidRange& range) { +    android::Parcel p; +    range.writeToParcel(&p); +    const int length = p.dataSize(); + +    jbyteArray parcelData = env->NewByteArray(length); +    env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data())); + +    return parcelData; +} diff --git a/services/tests/servicestests/jni/UidRangeTest.h b/services/tests/servicestests/jni/UidRangeTest.h new file mode 100644 index 000000000000..b7e745378800 --- /dev/null +++ b/services/tests/servicestests/jni/UidRangeTest.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_NET_UIDRANGETEST_H_ +#define _ANDROID_NET_UIDRANGETEST_H_ + +#include <jni.h> + +#include "android/net/UidRange.h" + +android::net::UidRange unmarshall(JNIEnv* env, jbyteArray parcelData); + +jbyteArray marshall(JNIEnv* env, const android::net::UidRange& range); + +extern "C" +JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass, +        jbyteArray inParcel); + +extern "C" +JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel); + +extern "C" +JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel); + +#endif  //  _ANDROID_NET_UIDRANGETEST_H_ diff --git a/services/tests/servicestests/src/android/net/UidRangeTest.java b/services/tests/servicestests/src/android/net/UidRangeTest.java new file mode 100644 index 000000000000..221fe0f99f0b --- /dev/null +++ b/services/tests/servicestests/src/android/net/UidRangeTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *      http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; + +import junit.framework.TestCase; + +import static org.junit.Assert.assertArrayEquals; + +public class UidRangeTest extends TestCase { + +    static { +        System.loadLibrary("servicestestsjni"); +    } + +    private static native byte[] readAndWriteNative(byte[] inParcel); +    private static native int getStart(byte[] inParcel); +    private static native int getStop(byte[] inParcel); + +    @SmallTest +    public void testNativeParcelUnparcel() { +        UidRange original = new UidRange(1234, Integer.MAX_VALUE); + +        byte[] inParcel = marshall(original); +        byte[] outParcel = readAndWriteNative(inParcel); +        UidRange roundTrip = unmarshall(outParcel); + +        assertEquals(original, roundTrip); +        assertArrayEquals(inParcel, outParcel); +    } + +    @SmallTest +    public void testIndividualNativeFields() { +        UidRange original = new UidRange(0x11115678, 0x22224321); +        byte[] originalBytes = marshall(original); + +        assertEquals(original.start, getStart(originalBytes)); +        assertEquals(original.stop, getStop(originalBytes)); +    } + +    @SmallTest +    public void testSingleItemUidRangeAllowed() { +        new UidRange(123, 123); +        new UidRange(0, 0); +        new UidRange(Integer.MAX_VALUE, Integer.MAX_VALUE); +    } + +    @SmallTest +    public void testNegativeUidsDisallowed() { +        try { +            new UidRange(-2, 100); +            fail("Exception not thrown for negative start UID"); +        } catch (IllegalArgumentException expected) { +        } + +        try { +            new UidRange(-200, -100); +            fail("Exception not thrown for negative stop UID"); +        } catch (IllegalArgumentException expected) { +        } +    } + +    @SmallTest +    public void testStopLessThanStartDisallowed() { +        final int x = 4195000; +        try { +            new UidRange(x, x - 1); +            fail("Exception not thrown for negative-length UID range"); +        } catch (IllegalArgumentException expected) { +        } +    } + +    /** +     * Write a {@link UidRange} into an empty parcel and return the underlying data. +     * +     * @see unmarshall(byte[]) +     */ +    private static byte[] marshall(UidRange range) { +        Parcel p = Parcel.obtain(); +        range.writeToParcel(p, /* flags */ 0); +        p.setDataPosition(0); +        return p.marshall(); +    } + +    /** +     * Read raw bytes into a parcel, and read a {@link UidRange} back out of them. +     * +     * @see marshall(UidRange) +     */ +    private static UidRange unmarshall(byte[] data) { +        Parcel p = Parcel.obtain(); +        p.unmarshall(data, 0, data.length); +        p.setDataPosition(0); +        return UidRange.CREATOR.createFromParcel(p); +    } +} diff --git a/services/tests/servicestests/src/com/android/server/ApfTest.java b/services/tests/servicestests/src/com/android/server/ApfTest.java index 640a6c927ed3..9ba27cbb6980 100644 --- a/services/tests/servicestests/src/com/android/server/ApfTest.java +++ b/services/tests/servicestests/src/com/android/server/ApfTest.java @@ -43,7 +43,7 @@ public class ApfTest extends AndroidTestCase {      public void setUp() throws Exception {          super.setUp();          // Load up native shared library containing APF interpreter exposed via JNI. -        System.loadLibrary("apfjni"); +        System.loadLibrary("servicestestsjni");      }      // Expected return codes from APF interpreter. diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 5ac697f99e18..15d76fd3ff59 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -630,6 +630,20 @@ public class CarrierConfigManager {      public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";      /** +     * If carriers require differentiate un-provisioned status: cold sim or out of credit sim +     * a package name and activity name can be provided to launch a supported carrier application +     * that check the sim provisioning status +     * The first element is the package name and the second element is the activity name +     * of the provisioning app +     * example: +     * <item>com.google.android.carrierPackageName</item> +     * <item>com.google.android.carrierPackageName.CarrierActivityName</item> +     * @hide +     */ +     public static final String KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY = +            "sim_state_detection_carrier_app_string_array"; + +    /**       * Determines whether the carrier supports making non-emergency phone calls while the phone is       * in emergency callback mode.  Default value is {@code true}, meaning that non-emergency calls       * are allowed in emergency callback mode. @@ -798,6 +812,10 @@ public class CarrierConfigManager {          sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");          sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);          sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false); + +        // Used for Sim card State detection app +        sDefaults.putStringArray(KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY, +                null);      }      /** diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index 6229ed921bcc..b5cf212e67e6 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -90,6 +90,14 @@ public class SubscriptionInfo implements Parcelable {      private int mDataRoaming;      /** +     * Sim Provisioning Status: +     * {@See SubscriptionManager#SIM_PROVISIONED} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT} +     */ +    private int mSimProvisioningStatus; + +    /**       * SIM Icon bitmap       */      private Bitmap mIconBitmap; @@ -114,7 +122,7 @@ public class SubscriptionInfo implements Parcelable {       */      public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,              CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, -            Bitmap icon, int mcc, int mnc, String countryIso) { +            Bitmap icon, int mcc, int mnc, String countryIso, int simProvisioningStatus) {          this.mId = id;          this.mIccId = iccId;          this.mSimSlotIndex = simSlotIndex; @@ -128,6 +136,7 @@ public class SubscriptionInfo implements Parcelable {          this.mMcc = mcc;          this.mMnc = mnc;          this.mCountryIso = countryIso; +        this.mSimProvisioningStatus = simProvisioningStatus;      }      /** @@ -264,6 +273,17 @@ public class SubscriptionInfo implements Parcelable {      }      /** +     * @return Sim Provisioning Status +     * {@See SubscriptionManager#SIM_PROVISIONED} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT} +     * @hide +     */ +    public int getSimProvisioningStatus() { +        return this.mSimProvisioningStatus; +    } + +    /**       * @return the MCC.       */      public int getMcc() { @@ -299,10 +319,12 @@ public class SubscriptionInfo implements Parcelable {              int mcc = source.readInt();              int mnc = source.readInt();              String countryIso = source.readString(); +            int simProvisioningStatus = source.readInt();              Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);              return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName, -                    nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso); +                    nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso, +                    simProvisioningStatus);          }          @Override @@ -325,6 +347,7 @@ public class SubscriptionInfo implements Parcelable {          dest.writeInt(mMcc);          dest.writeInt(mMnc);          dest.writeString(mCountryIso); +        dest.writeInt(mSimProvisioningStatus);          mIconBitmap.writeToParcel(dest, flags);      } @@ -355,6 +378,6 @@ public class SubscriptionInfo implements Parcelable {                  + " displayName=" + mDisplayName + " carrierName=" + mCarrierName                  + " nameSource=" + mNameSource + " iconTint=" + mIconTint                  + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc -                + " mnc " + mMnc + "}"; +                + " mnc " + mMnc + " SimProvisioningStatus " + mSimProvisioningStatus +"}";      }  } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index f3b0ce22081e..c49966a62925 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -232,6 +232,22 @@ public class SubscriptionManager {      /** Indicates that data roaming is disabled for a subscription */      public static final int DATA_ROAMING_DISABLE = 0; +    /** Sim provisioning status: provisioned */ +    /** @hide */ +    public static final int SIM_PROVISIONED = 0; + +    /** Sim provisioning status: un-provisioned due to cold sim */ +    /** @hide */ +    public static final int SIM_UNPROVISIONED_COLD = 1; + +    /** Sim provisioning status: un-provisioned due to out of credit */ +    /** @hide */ +    public static final int SIM_UNPROVISIONED_OUT_OF_CREDIT = 2; + +    /** Maximum possible sim provisioning status */ +    /** @hide */ +    public static final int MAX_SIM_PROVISIONING_STATUS = SIM_UNPROVISIONED_OUT_OF_CREDIT; +      /** @hide */      public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE; @@ -250,6 +266,13 @@ public class SubscriptionManager {      public static final String MNC = "mnc";      /** +     * TelephonyProvider column name for the sim provisioning status associated with a SIM. +     * <P>Type: INTEGER (int)</P> +     * @hide +     */ +    public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status"; + +    /**       *  TelephonyProvider column name for extreme threat in CB settings       * @hide       */ @@ -820,6 +843,40 @@ public class SubscriptionManager {      }      /** +     * Set Sim Provisioning Status by subscription ID +     * @param simProvisioningStatus with the subscription +     * {@See SubscriptionManager#SIM_PROVISIONED} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT} +     * @param subId the unique SubInfoRecord index in database +     * @return the number of records updated +     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required +     * @hide +     */ +    public int setSimProvisioningStatus(int simProvisioningStatus, int subId) { +        if (VDBG) { +            logd("[setSimProvisioningStatus]+ status:" + simProvisioningStatus + " subId:" + subId); +        } +        if (simProvisioningStatus < 0 || simProvisioningStatus > MAX_SIM_PROVISIONING_STATUS || +                !isValidSubscriptionId(subId)) { +            logd("[setSimProvisioningStatus]- fail"); +            return -1; +        } + +        int result = 0; + +        try { +            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); +            if (iSub != null) { +                result = iSub.setSimProvisioningStatus(simProvisioningStatus, subId); +            } +        } catch (RemoteException ex) { +            // ignore it +        } +        return result; +    } + +    /**       * Get slotId associated with the subscription.       * @return slotId as a positive integer or a negative value if an error either       * SIM_NOT_INSERTED or < 0 if an invalid slot index diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index ccabace44763..e4981ce7cddd 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -103,6 +103,7 @@ public class DctConstants {      public static final int EVENT_DATA_RAT_CHANGED = BASE + 41;      public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42;      public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43; +    public static final int EVENT_REDIRECTION_DETECTED = BASE + 44;      /***** Constants *****/ diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl index f6aef0859e90..c61ed2a7e62c 100755 --- a/telephony/java/com/android/internal/telephony/ISub.aidl +++ b/telephony/java/com/android/internal/telephony/ISub.aidl @@ -118,6 +118,17 @@ interface ISub {      int setDisplayName(String displayName, int subId);      /** +     * Set Sim Provisioning Status by subscription ID +     * @param simProvisionStatus with the subscription: +     * {@See SubscriptionManager#SIM_PROVISIONED} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_COLD} +     * {@See SubscriptionManager#SIM_UNPROVISIONED_OUT_OF_CREDIT} +     * @param subId the unique SubInfoRecord index in database +     * @return the number of records updated +     */ +    int setSimProvisioningStatus(int simProvisioningStatus, int subId); + +    /**       * Set display name by simInfo index with name source       * @param displayName the display name of SIM card       * @param subId the unique SubscriptionInfo index in database diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index c70f8cf2fdfc..eafb3d40d17e 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -395,4 +395,32 @@ public class TelephonyIntents {       */      public static final String ACTION_SET_RADIO_CAPABILITY_FAILED =              "android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED"; + +    /** +     * <p>Broadcast Action: when data connections get redirected with validation failure. +     * intended for sim/account status checks and only sent to the specified carrier app +     * feedback is via carrier/system APIs to report cold-sim, out-of-credit-sim, etc +     * The intent will have the following extra values:</p> +     * <ul> +     *   <li>redirectUrl</li><dd>A string with the redirection url info.</dd> +     *   <li>subId</li><dd>Sub Id which associated the data redirection.</dd> +     * </ul> +     * <p class="note">This is a protected intent that can only be sent by the system.</p> +     */ +    public static final String ACTION_DATA_CONNECTION_REDIRECTED = +            "android.intent.action.REDIRECTION_DETECTED"; +    /** +     * <p>Broadcast Action: when data connections setup fails. +     * intended for sim/account status checks and only sent to the specified carrier app +     * feedback is via carrier/system APIs to report cold-sim, out-of-credit-sim, etc +     * The intent will have the following extra values:</p> +     * <ul> +     *   <li>apnType</li><dd>A string with the apn type.</dd> +     *   <li>errorCode</li><dd>A integer with dataFailCause.</dd> +     *   <li>subId</dt><li>Sub Id which associated the data redirection.</dd> +     * </ul> +     * <p class="note">This is a protected intent that can only be sent by the system. </p> +     */ +    public static final String ACTION_REQUEST_NETWORK_FAILED = +            "android.intent.action.REQUEST_NETWORK_FAILED";  }  |