diff options
209 files changed, 3310 insertions, 1937 deletions
| diff --git a/Android.bp b/Android.bp index 70438d200cb7..18e9fdb9e3f7 100644 --- a/Android.bp +++ b/Android.bp @@ -1065,7 +1065,7 @@ doc_defaults {          "ext",          "framework",          "voip-common", -        "android.test.mock", +        "android.test.mock.impl",      ],      local_sourcepaths: frameworks_base_subdirs,      html_dirs: [ @@ -1202,7 +1202,7 @@ doc_defaults {          "ext",          "framework",          "voip-common", -        "android.test.mock", +        "android.test.mock.impl",      ],      local_sourcepaths: frameworks_base_subdirs,      installable: false, @@ -1563,3 +1563,10 @@ droiddoc {          },      },  } + +filegroup { +    name: "framework-annotation-nonnull-srcs", +    srcs: [ +        "core/java/android/annotation/NonNull.java", +    ], +} diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 8ffe5bf59315..ed6c25dc49c3 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -302,6 +302,7 @@ status_t BootAnimation::readyToRun() {      mHeight = h;      mFlingerSurfaceControl = control;      mFlingerSurface = s; +    mTargetInset = -1;      // If the device has encryption turned on or is in process      // of being encrypted we show the encrypted boot animation. @@ -942,6 +943,7 @@ bool BootAnimation::playAnimation(const Animation& animation)                  if (mClockEnabled && mTimeIsAccurate && validClock(part)) {                      drawClock(animation.clockFont, part.clockPosX, part.clockPosY);                  } +                handleViewport(frameDuration);                  eglSwapBuffers(mDisplay, mSurface); @@ -966,7 +968,7 @@ bool BootAnimation::playAnimation(const Animation& animation)              usleep(part.pause * ns2us(frameDuration));              // For infinite parts, we've now played them at least once, so perhaps exit -            if(exitPending() && !part.count) +            if(exitPending() && !part.count && mCurrentInset >= mTargetInset)                  break;          } @@ -986,6 +988,51 @@ bool BootAnimation::playAnimation(const Animation& animation)      return true;  } +void BootAnimation::handleViewport(nsecs_t timestep) { +    if (mShuttingDown || !mFlingerSurfaceControl || mTargetInset == 0) { +        return; +    } +    if (mTargetInset < 0) { +        // Poll the amount for the top display inset. This will return -1 until persistent properties +        // have been loaded. +        mTargetInset = android::base::GetIntProperty("persist.sys.displayinset.top", +                -1 /* default */, -1 /* min */, mHeight / 2 /* max */); +    } +    if (mTargetInset <= 0) { +        return; +    } + +    if (mCurrentInset < mTargetInset) { +        // After the device boots, the inset will effectively be cropped away. We animate this here. +        float fraction = static_cast<float>(mCurrentInset) / mTargetInset; +        int interpolatedInset = (cosf((fraction + 1) * M_PI) / 2.0f + 0.5f) * mTargetInset; + +        SurfaceComposerClient::Transaction() +                .setCrop(mFlingerSurfaceControl, Rect(0, interpolatedInset, mWidth, mHeight)) +                .apply(); +    } else { +        // At the end of the animation, we switch to the viewport that DisplayManager will apply +        // later. This changes the coordinate system, and means we must move the surface up by +        // the inset amount. +        sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay( +                ISurfaceComposer::eDisplayIdMain)); + +        Rect layerStackRect(0, 0, mWidth, mHeight - mTargetInset); +        Rect displayRect(0, mTargetInset, mWidth, mHeight); + +        SurfaceComposerClient::Transaction t; +        t.setPosition(mFlingerSurfaceControl, 0, -mTargetInset) +                .setCrop(mFlingerSurfaceControl, Rect(0, mTargetInset, mWidth, mHeight)); +        t.setDisplayProjection(dtoken, 0 /* orientation */, layerStackRect, displayRect); +        t.apply(); + +        mTargetInset = mCurrentInset = 0; +    } + +    int delta = timestep * mTargetInset / ms2ns(200); +    mCurrentInset += delta; +} +  void BootAnimation::releaseAnimation(Animation* animation) const  {      for (Vector<Animation::Part>::iterator it = animation->parts.begin(), diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 56e131523bcb..b4699d884681 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -157,11 +157,15 @@ private:      void checkExit(); +    void handleViewport(nsecs_t timestep); +      sp<SurfaceComposerClient>       mSession;      AssetManager mAssets;      Texture     mAndroid[2];      int         mWidth;      int         mHeight; +    int         mCurrentInset; +    int         mTargetInset;      bool        mUseNpotTextures = false;      EGLDisplay  mDisplay;      EGLDisplay  mContext; diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index be2e2faf3739..f0a0e88310f9 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -30,7 +30,6 @@ import android.content.res.Resources;  import android.content.res.TypedArray;  import android.content.res.XmlResourceParser;  import android.hardware.fingerprint.FingerprintManager; -import android.os.Build;  import android.os.Parcel;  import android.os.Parcelable;  import android.util.AttributeSet; @@ -190,12 +189,10 @@ public class AccessibilityServiceInfo implements Parcelable {       * content and also the accessibility service will receive accessibility events from       * them.       * <p> -     * <strong>Note:</strong> For accessibility services targeting API version -     * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly -     * set for the system to regard views that are not important for accessibility. For -     * accessibility services targeting API version lower than -     * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are -     * regarded for accessibility purposes. +     * <strong>Note:</strong> For accessibility services targeting Android 4.1 (API level 16) or +     * higher, this flag has to be explicitly set for the system to regard views that are not +     * important for accessibility. For accessibility services targeting Android 4.0.4 (API level +     * 15) or lower, this flag is ignored and all views are regarded for accessibility purposes.       * </p>       * <p>       * Usually views not important for accessibility are layout managers that do not @@ -220,19 +217,19 @@ public class AccessibilityServiceInfo implements Parcelable {       * flag does not guarantee that the device will not be in touch exploration       * mode since there may be another enabled service that requested it.       * <p> -     * For accessibility services targeting API version higher than -     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set -     * this flag have to declare this capability in their meta-data by setting -     * the attribute {@link android.R.attr#canRequestTouchExplorationMode -     * canRequestTouchExplorationMode} to true, otherwise this flag will +     * For accessibility services targeting Android 4.3 (API level 18) or higher +     * that want to set this flag have to declare this capability in their +     * meta-data by setting the attribute +     * {@link android.R.attr#canRequestTouchExplorationMode +     * canRequestTouchExplorationMode} to true. Otherwise, this flag will       * be ignored. For how to declare the meta-data of a service refer to       * {@value AccessibilityService#SERVICE_META_DATA}.       * </p>       * <p> -     * Services targeting API version equal to or lower than -     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. -     * the first time they are run, if this flag is specified, a dialog is -     * shown to the user to confirm enabling explore by touch. +     * Services targeting Android 4.2.2 (API level 17) or lower will work +     * normally. In other words, the first time they are run, if this flag is +     * specified, a dialog is shown to the user to confirm enabling explore by +     * touch.       * </p>       * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode       */ @@ -388,10 +385,10 @@ public class AccessibilityServiceInfo implements Parcelable {      public int feedbackType;      /** -     * The timeout after the most recent event of a given type before an +     * The timeout, in milliseconds, after the most recent event of a given type before an       * {@link AccessibilityService} is notified.       * <p> -     *   <strong>Can be dynamically set at runtime.</strong>. +     *   <strong>Can be dynamically set at runtime.</strong>       * </p>       * <p>       * <strong>Note:</strong> The event notification timeout is useful to avoid propagating diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 7f4ea1d0c532..cdcba9b0d91a 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6377,6 +6377,10 @@ public class Activity extends ContextThemeWrapper      }      void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { +        if (args != null && args.length > 0 && args[0].equals("--autofill")) { +            dumpAutofillManager(prefix, writer); +            return; +        }          writer.print(prefix); writer.print("Local Activity ");                  writer.print(Integer.toHexString(System.identityHashCode(this)));                  writer.println(" State:"); @@ -6404,16 +6408,20 @@ public class Activity extends ContextThemeWrapper          mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix); +        dumpAutofillManager(prefix, writer); + +        ResourcesManager.getInstance().dump(prefix, writer); +    } + +    void dumpAutofillManager(String prefix, PrintWriter writer) {          final AutofillManager afm = getAutofillManager();          if (afm != null) { +            afm.dump(prefix, writer);              writer.print(prefix); writer.print("Autofill Compat Mode: ");              writer.println(isAutofillCompatibilityEnabled()); -            afm.dump(prefix, writer);          } else {              writer.print(prefix); writer.println("No AutofillManager");          } - -        ResourcesManager.getInstance().dump(prefix, writer);      }      /** diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 9b6764d96fb2..14cae95508e7 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -413,4 +413,9 @@ public abstract class ActivityManagerInternal {       * @return The intent used to launch the home activity.       */      public abstract Intent getHomeIntent(); + +    /** +     * WindowManager notifies AM when display size of the default display changes. +     */ +    public abstract void notifyDefaultDisplaySizeChanged();  } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index b2b85d442301..d526bccf90a9 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -960,14 +960,15 @@ public class ActivityOptions {      }      /** -     * Sets the bounds (window size) that the activity should be launched in. +     * Sets the bounds (window size and position) that the activity should be launched in.       * Rect position should be provided in pixels and in screen coordinates. -     * Set to null explicitly for fullscreen. +     * Set to {@code null} to explicitly launch fullscreen.       * <p> -     * <strong>NOTE:<strong/> This value is ignored on devices that don't have +     * <strong>NOTE:</strong> This value is ignored on devices that don't have       * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or       * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled. -     * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen. +     * @param screenSpacePixelRect launch bounds or {@code null} for fullscreen +     * @return {@code this} {@link ActivityOptions} instance       */      public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {          mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9c516d26bb71..9e06e9faca02 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -147,6 +147,7 @@ import com.android.internal.os.RuntimeInit;  import com.android.internal.os.SomeArgs;  import com.android.internal.util.ArrayUtils;  import com.android.internal.util.FastPrintWriter; +import com.android.internal.util.Preconditions;  import com.android.internal.util.function.pooled.PooledLambda;  import com.android.org.conscrypt.OpenSSLSocketImpl;  import com.android.org.conscrypt.TrustedCertificateStore; @@ -5244,6 +5245,16 @@ public final class ActivityThread extends ClientTransactionHandler {          }      } +    /** +     * Updates the application info. +     * +     * This only works in the system process. Must be called on the main thread. +     */ +    public void handleSystemApplicationInfoChanged(@NonNull ApplicationInfo ai) { +        Preconditions.checkState(mSystemThread, "Must only be called in the system process"); +        handleApplicationInfoChanged(ai); +    } +      void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {          // Updates triggered by package installation go through a package update          // receiver. Here we try to capture ApplicationInfo changes that are diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 68869c65d7c9..2d9fbf974397 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -125,10 +125,13 @@ public class ResourcesManager {          }      } +    private static final boolean ENABLE_APK_ASSETS_CACHE = false; +      /**       * The ApkAssets we are caching and intend to hold strong references to.       */ -    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(3); +    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = +            (ENABLE_APK_ASSETS_CACHE) ? new LruCache<>(3) : null;      /**       * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't @@ -316,9 +319,12 @@ public class ResourcesManager {      private @NonNull ApkAssets loadApkAssets(String path, boolean sharedLib, boolean overlay)              throws IOException {          final ApkKey newKey = new ApkKey(path, sharedLib, overlay); -        ApkAssets apkAssets = mLoadedApkAssets.get(newKey); -        if (apkAssets != null) { -            return apkAssets; +        ApkAssets apkAssets = null; +        if (mLoadedApkAssets != null) { +            apkAssets = mLoadedApkAssets.get(newKey); +            if (apkAssets != null) { +                return apkAssets; +            }          }          // Optimistically check if this ApkAssets exists somewhere else. @@ -326,7 +332,10 @@ public class ResourcesManager {          if (apkAssetsRef != null) {              apkAssets = apkAssetsRef.get();              if (apkAssets != null) { -                mLoadedApkAssets.put(newKey, apkAssets); +                if (mLoadedApkAssets != null) { +                    mLoadedApkAssets.put(newKey, apkAssets); +                } +                  return apkAssets;              } else {                  // Clean up the reference. @@ -341,7 +350,11 @@ public class ResourcesManager {          } else {              apkAssets = ApkAssets.loadFromPath(path, false /*system*/, sharedLib);          } -        mLoadedApkAssets.put(newKey, apkAssets); + +        if (mLoadedApkAssets != null) { +            mLoadedApkAssets.put(newKey, apkAssets); +        } +          mCachedApkAssets.put(newKey, new WeakReference<>(apkAssets));          return apkAssets;      } @@ -441,18 +454,22 @@ public class ResourcesManager {              pw.println("ResourcesManager:");              pw.increaseIndent(); -            pw.print("cached apks: total="); -            pw.print(mLoadedApkAssets.size()); -            pw.print(" created="); -            pw.print(mLoadedApkAssets.createCount()); -            pw.print(" evicted="); -            pw.print(mLoadedApkAssets.evictionCount()); -            pw.print(" hit="); -            pw.print(mLoadedApkAssets.hitCount()); -            pw.print(" miss="); -            pw.print(mLoadedApkAssets.missCount()); -            pw.print(" max="); -            pw.print(mLoadedApkAssets.maxSize()); +            if (mLoadedApkAssets != null) { +                pw.print("cached apks: total="); +                pw.print(mLoadedApkAssets.size()); +                pw.print(" created="); +                pw.print(mLoadedApkAssets.createCount()); +                pw.print(" evicted="); +                pw.print(mLoadedApkAssets.evictionCount()); +                pw.print(" hit="); +                pw.print(mLoadedApkAssets.hitCount()); +                pw.print(" miss="); +                pw.print(mLoadedApkAssets.missCount()); +                pw.print(" max="); +                pw.print(mLoadedApkAssets.maxSize()); +            } else { +                pw.print("cached apks: 0 [cache disabled]"); +            }              pw.println();              pw.print("total apks: "); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 7bcc209c6500..eb8d8d37ae29 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3889,6 +3889,11 @@ public class DevicePolicyManager {      /**       * Installs the given certificate as a user CA. +     * <p> +     * Inserted user CAs aren't automatically trusted by apps in Android 7.0 (API level 24) and +     * higher. App developers can change the default behavior for an app by adding a +     * <a href="{@docRoot}training/articles/security-config.html">Security Configuration +     * File</a> to the app manifest file.       *       * The caller must be a profile or device owner on that user, or a delegate package given the       * {@link #DELEGATION_CERT_INSTALL} scope via {@link #setDelegatedScopes}; otherwise a diff --git a/core/java/android/app/admin/SystemUpdatePolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java index 2a451ff07672..bcd5f6c7497f 100644 --- a/core/java/android/app/admin/SystemUpdatePolicy.java +++ b/core/java/android/app/admin/SystemUpdatePolicy.java @@ -76,9 +76,7 @@ import java.util.stream.Collectors;   * </code></pre>   *   * <h3>Developer guide</h3> - * To learn more about managing system updates, read - * <a href="{@docRoot}/work/dpc/security.html#control_remote_software_updates">Control remote - * software updates</a>. + * To learn more, read <a href="{@docRoot}work/dpc/system-updates">Manage system updates</a>.   *   * @see DevicePolicyManager#setSystemUpdatePolicy   * @see DevicePolicyManager#getSystemUpdatePolicy diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index d568662409d7..dd61f286c88e 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -41,18 +41,23 @@ import java.util.Arrays;  import java.util.List;  /** - * Assist data automatically created by the platform's implementation of assist and autofill. + * <p>This API automatically creates assist data from the platform's + * implementation of assist and autofill.   *   * <p>The structure is used for assist purposes when created by   * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},   * or {@link View#onProvideVirtualStructure(ViewStructure)}.   * - * <p>The structure is used for autofill purposes when created by + * <p>The structure is also used for autofill purposes when created by   * {@link View#onProvideAutofillStructure(ViewStructure, int)},   * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.   * - * <p>For performance reasons, some properties of the assist data might be available just for assist - * or autofill purposes; in those case, the property availability will be document in its javadoc. + * <p>For performance reasons, some properties of the assist data might only be available for + * assist or autofill purposes. In those cases, a property's availability will be documented + * in its javadoc. + * + * <p>To learn about using Autofill in your app, read the + * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.   */  public class AssistStructure implements Parcelable {      static final String TAG = "AssistStructure"; diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java index 7ab3d8bdd857..5694ca860453 100644 --- a/core/java/android/appwidget/AppWidgetManagerInternal.java +++ b/core/java/android/appwidget/AppWidgetManagerInternal.java @@ -16,12 +16,9 @@  package android.appwidget; -import android.annotation.NonNull;  import android.annotation.Nullable;  import android.util.ArraySet; -import java.util.Set; -  /**   * App widget manager local system service interface.   * @@ -36,4 +33,13 @@ public abstract class AppWidgetManagerInternal {       * @return Whether the UID hosts widgets from the package.       */      public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid); + +    /** +     * Execute the widget-related work of unlocking a user.  This is intentionally +     * invoked just <em>before</em> the boot-completed broadcast is issued, after +     * the data-related work of unlock has completed. +     * +     * @param userId The user that is being unlocked. +     */ +    public abstract void unlockUser(int userId);  } diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index 925fa4a7c567..60ac1f08ba66 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -21,7 +21,6 @@ import android.annotation.SystemService;  import android.annotation.TestApi;  import android.annotation.UnsupportedAppUsage;  import android.annotation.UserIdInt; -import android.app.Activity;  import android.app.usage.UsageStatsManager;  import android.content.Context;  import android.content.Intent; @@ -30,256 +29,23 @@ import android.graphics.drawable.AdaptiveIconDrawable;  import android.os.Build.VERSION_CODES;  import android.os.RemoteException;  import android.os.ServiceManager; -import android.os.UserHandle;  import com.android.internal.annotations.VisibleForTesting;  import java.util.List;  /** - * The ShortcutManager performs operations on an app's set of <em>shortcuts</em>. The - * {@link ShortcutInfo} class contains information about each of the shortcuts themselves. + * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which + * represent specific tasks and actions that users can perform within your app. This page lists + * components of the <code>ShortcutManager</code> class that you can use to create and manage + * sets of shortcuts.   * - * <p>An app's shortcuts represent specific tasks and actions that users can perform within your - * app. When a user selects a shortcut in the currently-active launcher, your app opens an activity - * other than the app's starting activity, provided that the currently-active launcher supports app - * shortcuts.</p> + * <p>To learn about methods that retrieve information about a single shortcut—including + * identifiers, type, and status—read the <code> + * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference.   * - * <p>The types of shortcuts that you create for your app depend on the app's key use cases. For - * example, an email app may publish the "compose new email" shortcut, which allows the app to - * directly open the compose activity.</p> - * - * <p class="note"><b>Note:</b> Only main activities—activities that handle the - * {@link Intent#ACTION_MAIN} action and the {@link Intent#CATEGORY_LAUNCHER} category—can - * have shortcuts. If an app has multiple main activities, you need to define the set of shortcuts - * for <em>each</em> activity. - * - * <p>This page discusses the implementation details of the <code>ShortcutManager</code> class. For - * definitions of key terms and guidance on performing operations on shortcuts within your app, see - * the <a href="/guide/topics/ui/shortcuts.html">App Shortcuts</a> feature guide. - * - * <h3>Shortcut characteristics</h3> - * - * This section describes in-depth details about each shortcut type's usage and availability. - * - * <p class="note"><b>Important security note:</b> All shortcut information is stored in - * <a href="/training/articles/direct-boot.html">credential encrypted storage</a>, so your app - * cannot access a user's shortcuts until after they've unlocked the device. - * - * <h4>Static and dynamic shortcuts</h4> - * - * <p>Static shortcuts and dynamic shortcuts are shown in a supported launcher when the user - * performs a specific gesture. On currently-supported launchers, the gesture is a long-press on the - * app's launcher icon, but the actual gesture may be different on other launcher apps. - * - * <p>The {@link LauncherApps} class provides APIs for launcher apps to access shortcuts. - * - * <h4>Pinned shortcuts</h4> - * - * <p>Because pinned shortcuts appear in the launcher itself, they're always visible. A pinned - * shortcut is removed from the launcher only in the following situations: - * <ul> - *     <li>The user removes it. - *     <li>The publisher app associated with the shortcut is uninstalled. - *     <li>The user selects <b>Clear data</b> from the publisher app's <i>Storage</i> screen, within - *     the system's <b>Settings</b> app. - * </ul> - * - * <p>Because the system performs - * <a href="/guide/topics/ui/shortcuts.html#backup-and-restore">backup and restore</a> on pinned - * shortcuts automatically, these shortcuts' IDs should contain either stable, constant strings or - * server-side identifiers, rather than identifiers generated locally that might not make sense on - * other devices. - * - * <h3>Shortcut display order</h3> - * - * <p>When the launcher displays an app's shortcuts, they should appear in the following order: - * - * <ol> - *   <li><b>Static shortcuts:</b> Shortcuts whose {@link ShortcutInfo#isDeclaredInManifest()} method - *   returns {@code true}.</li> - *   <li><b>Dynamic shortcuts:</b> Shortcuts whose {@link ShortcutInfo#isDynamic()} method returns - *   {@code true}.</li> - * </ol> - * - * <p>Within each shortcut type (static and dynamic), shortcuts are sorted in order of increasing - * rank according to {@link ShortcutInfo#getRank()}.</p> - * - * <h4>Shortcut ranks</h4> - * - * <p>Shortcut ranks are non-negative, sequential integers that determine the order in which - * shortcuts appear, assuming that the shortcuts are all in the same category. You can update ranks - * of existing shortcuts when you call {@link #updateShortcuts(List)}, - * {@link #addDynamicShortcuts(List)}, or {@link #setDynamicShortcuts(List)}. - * - * <p class="note"><b>Note:</b> Ranks are auto-adjusted so that they're unique for each type of - * shortcut (static or dynamic). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and - * 2, adding another dynamic shortcut with a rank of 1 represents a request to place this shortcut - * at the second position. In response, the third and fourth shortcuts move closer to the bottom of - * the shortcut list, with their ranks changing to 2 and 3, respectively. - * - * <h3>Options for static shortcuts</h3> - * - * The following list includes descriptions for the different attributes within a static shortcut. - * You must provide a value for {@code android:shortcutId} and {@code android:shortcutShortLabel}; - * all other values are optional. - * - * <dl> - *   <dt>{@code android:shortcutId}</dt> - *   <dd><p>A string literal, which represents the shortcut when a {@code ShortcutManager} object - *   performs operations on it.</p> - *   <p class="note"><b>Note: </b>You cannot set this attribute's value to a resource string, such - *   as <code>@string/foo</code>.</p> - *   </dd> - * - *   <dt>{@code android:enabled}</dt> - *   <dd><p>Whether the user can interact with the shortcut from a supported launcher.</p> - *   <p>The default value is {@code true}. If you set it to {@code false}, you should also set - *   {@code android:shortcutDisabledMessage} to a message that explains why you've disabled the - *   shortcut. If you don't think you need to provide such a message, it's easiest to just remove - *   the shortcut from the XML file entirely, rather than changing the values of the shortcut's - *   {@code android:enabled} and {@code android:shortcutDisabledMessage} attributes. - *   </dd> - * - *   <dt>{@code android:icon}</dt> - *   <dd><p>The <a href="/topic/performance/graphics/index.html">bitmap</a> or - *   <a href="/guide/practices/ui_guidelines/icon_design_adaptive.html">adaptive icon</a> that the - *   launcher uses when displaying the shortcut to the user. This value can be either the path to an - *   image or the resource file that contains the image. Use adaptive icons whenever possible to - *   improve performance and consistency.</p> - *   <p class="note"><b>Note: </b>Shortcut icons cannot include - *   <a href="/training/material/drawables.html#DrawableTint">tints</a>. - *   </dd> - * - *   <dt>{@code android:shortcutShortLabel}</dt> - *   <dd><p>A concise phrase that describes the shortcut's purpose. For more information, see - *   {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}.</p> - *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as - *   <code>@string/shortcut_short_label</code>.</p> - *   </dd> - * - *   <dt>{@code android:shortcutLongLabel}</dt> - *   <dd><p>An extended phrase that describes the shortcut's purpose. If there's enough space, the - *   launcher displays this value instead of {@code android:shortcutShortLabel}. For more - *   information, see {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}.</p> - *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as - *   <code>@string/shortcut_long_label</code>.</p> - *   </dd> - * - *   <dt>{@code android:shortcutDisabledMessage}</dt> - *   <dd><p>The message that appears in a supported launcher when the user attempts to launch a - *   disabled shortcut. The message should explain to the user why the shortcut is now disabled. - *   This attribute's value has no effect if {@code android:enabled} is {@code true}.</p> - *   <p class="note"><b>Note: </b>This attribute's value must be a resource string, such as - *   <code>@string/shortcut_disabled_message</code>.</p> - *   </dd> - * </dl> - * - * <h3>Inner elements that define static shortcuts</h3> - * - * <p>The XML file that lists an app's static shortcuts supports the following elements inside each - * {@code <shortcut>} element. You must include an {@code intent} inner element for each - * static shortcut that you define.</p> - * - * <dl> - *   <dt>{@code intent}</dt> - *   <dd><p>The action that the system launches when the user selects the shortcut. This intent must - *   provide a value for the {@code android:action} attribute.</p> - *   <p>You can provide multiple intents for a single shortcut. If you do so, the last defined - *   activity is launched, and the other activities are placed in the - *   <a href="/guide/components/tasks-and-back-stack.html">back stack</a>. See - *   <a href="/guide/topics/ui/shortcuts.html#static">Using Static Shortcuts</a> and the - *   {@link android.app.TaskStackBuilder} class reference for details.</p> - *   <p class="note"><b>Note:</b> This {@code intent} element cannot include string resources.</p> - *   <p>To learn more about how to configure intents, see - *   <a href="{@docRoot}guide/topics/ui/settings.html#Intents">Using intents</a>.</p> - *   </dd> - * - *   <dt>{@code categories}</dt> - *   <dd><p>Provides a grouping for the types of actions that your app's shortcuts perform, such as - *   creating new chat messages.</p> - *   <p>For a list of supported shortcut categories, see the {@link ShortcutInfo} class reference - *   for a list of supported shortcut categories. - *   </dd> - * </dl> - * - * <h3>Updating shortcuts</h3> - * - * <p>Each app's launcher icon can contain at most {@link #getMaxShortcutCountPerActivity()} number - * of static and dynamic shortcuts combined. There is no limit to the number of pinned shortcuts - * that an app can create, though. - * - * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut, - * the pinned shortcut is still visible and launchable.  This allows an app to have more than - * {@link #getMaxShortcutCountPerActivity()} number of shortcuts. - * - * <p>As an example, suppose {@link #getMaxShortcutCountPerActivity()} is 5: - * <ol> - *     <li>A chat app publishes 5 dynamic shortcuts for the 5 most recent - *     conversations (c1, c2, ..., c5). - * - *     <li>The user pins all 5 of the shortcuts. - * - *     <li>Later, the user has started 3 additional conversations (c6, c7, and c8), so the publisher - *     app re-publishes its dynamic shortcuts. The new dynamic shortcut list is: c4, c5, ..., c8. - *     <p>The publisher app has to remove c1, c2, and c3 because it can't have more than 5 dynamic - *     shortcuts. However, c1, c2, and c3 are still pinned shortcuts that the user can access and - *     launch. - *     <p>At this point, the user can access a total of 8 shortcuts that link to activities in the - *     publisher app, including the 3 pinned shortcuts, even though an app can have at most 5 - *     dynamic shortcuts. - * - *     <li>The app can use {@link #updateShortcuts(List)} to update <em>any</em> of the existing - *     8 shortcuts, when, for example, the chat peers' icons have changed. - *     <p>The {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} methods - *     can also be used to update existing shortcuts with the same IDs, but they <b>cannot</b> be - *     used for updating non-dynamic, pinned shortcuts because these 2 methods try to convert the - *     given lists of shortcuts to dynamic shortcuts. - * </ol> - * - * <h3>Shortcut intents</h3> - * - * <p> - * Dynamic shortcuts can be published with any set of {@link Intent#addFlags Intent} flags. - * Typically, {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} is specified, possibly along with other - * flags; otherwise, if the app is already running, the app is simply brought to - * the foreground, and the target activity might not appear. - * - * <p>Static shortcuts <b>cannot</b> have custom intent flags. - * The first intent of a static shortcut will always have {@link Intent#FLAG_ACTIVITY_NEW_TASK} - * and {@link Intent#FLAG_ACTIVITY_CLEAR_TASK} set. This means, when the app is already running, all - * the existing activities in your app are destroyed when a static shortcut is launched. - * If this behavior is not desirable, you can use a <em>trampoline activity</em>, or an invisible - * activity that starts another activity in {@link Activity#onCreate}, then calls - * {@link Activity#finish()}: - * <ol> - *     <li>In the <code>AndroidManifest.xml</code> file, the trampoline activity should include the - *     attribute assignment {@code android:taskAffinity=""}. - *     <li>In the shortcuts resource file, the intent within the static shortcut should reference - *     the trampoline activity. - * </ol> - * - * <h3>Rate limiting</h3> - * - * <p>When <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate limiting</a> is active, - * {@link #isRateLimitingActive()} returns {@code true}. - * - * <p>Rate limiting is reset upon certain events, so even background apps can call these APIs until - * the rate limit is reached again. These events include the following: - * <ul> - *   <li>An app comes to the foreground. - *   <li>The system locale changes. - *   <li>The user performs the <a href="/guide/topics/ui/notifiers/notifications.html#direct">inline - *   reply</a> action on a notification. - * </ul> - * - * <h3>Handling system locale changes</h3> - * - * <p>Apps should update dynamic and pinned shortcuts when they receive the - * {@link Intent#ACTION_LOCALE_CHANGED} broadcast, indicating that the system locale has changed. - * <p>When the system locale changes, <a href="/guide/topics/ui/shortcuts.html#rate-limit">rate - * limiting</a> is reset, so even background apps can add and update dynamic shortcuts until the - * rate limit is reached again. + * <p>For guidance about using shortcuts, see + * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>.   *   * <h3>Retrieving class instances</h3>   * <!-- Provides a heading for the content filled in by the @SystemService annotation below --> @@ -460,8 +226,9 @@ public class ShortcutManager {      }      /** -     * Disable pinned shortcuts.  For more details, see the Javadoc for the {@link ShortcutManager} -     * class. +     * Disable pinned shortcuts.  For more details, read +     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts"> +     * Disable shortcuts</a>.       *       * @throws IllegalArgumentException If trying to disable immutable shortcuts.       * @@ -500,7 +267,9 @@ public class ShortcutManager {      /**       * Disable pinned shortcuts, showing the user a custom error message when they try to select       * the disabled shortcuts. -     * For more details, see the Javadoc for the {@link ShortcutManager} class. +     * For more details, read +     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts"> +     * Disable shortcuts</a>.       *       * @throws IllegalArgumentException If trying to disable immutable shortcuts.       * @@ -588,7 +357,8 @@ public class ShortcutManager {      /**       * Return {@code true} when rate-limiting is active for the caller app.       * -     * <p>See the class level javadoc for details. +     * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting"> +     * Rate limiting</a>.       *       * @throws IllegalStateException when the user is locked.       */ @@ -634,7 +404,9 @@ public class ShortcutManager {       * Apps that publish shortcuts should call this method whenever the user       * selects the shortcut containing the given ID or when the user completes       * an action in the app that is equivalent to selecting the shortcut. -     * For more details, see the Javadoc for the {@link ShortcutManager} class +     * For more details, read about +     * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage"> +     * tracking shortcut usage</a>.       *       * <p>The information is accessible via {@link UsageStatsManager#queryEvents}       * Typically, launcher apps use this information to build a prediction model @@ -702,7 +474,9 @@ public class ShortcutManager {       * @param resultIntent If not null, this intent will be sent when the shortcut is pinned.       *    Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.       *    To avoid background execution limits, use an unexported, manifest-declared receiver. -     *    For more details, see the overview documentation for the {@link ShortcutManager} class. +     *    For more details, see +     *    <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned"> +     *    Creating pinned shortcuts</a>.       *       * @return {@code TRUE} if the launcher supports this feature.  Note the API will return without       *    waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 424da7602a58..25d98f7edf06 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -1757,7 +1757,8 @@ public final class SQLiteDatabase extends SQLiteClosable {          executeSql(sql, bindArgs);      } -    private int executeSql(String sql, Object[] bindArgs) throws SQLException { +    /** {@hide} */ +    public int executeSql(String sql, Object[] bindArgs) throws SQLException {          acquireReference();          try {              final int statementType = DatabaseUtils.getSqlStatementType(sql); diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java index 1bd44fa5c2c6..a984200c0920 100644 --- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java +++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java @@ -16,18 +16,26 @@  package android.database.sqlite; +import android.annotation.NonNull; +import android.annotation.Nullable;  import android.annotation.UnsupportedAppUsage; +import android.content.ContentValues;  import android.database.Cursor;  import android.database.DatabaseUtils; +import android.os.Build;  import android.os.CancellationSignal;  import android.os.OperationCanceledException;  import android.provider.BaseColumns;  import android.text.TextUtils;  import android.util.Log; +import libcore.util.EmptyArray; + +import java.util.Arrays;  import java.util.Iterator;  import java.util.Map;  import java.util.Map.Entry; +import java.util.Objects;  import java.util.Set;  import java.util.regex.Pattern; @@ -99,9 +107,6 @@ public class SQLiteQueryBuilder          if (mWhereClause == null) {              mWhereClause = new StringBuilder(inWhere.length() + 16);          } -        if (mWhereClause.length() == 0) { -            mWhereClause.append('('); -        }          mWhereClause.append(inWhere);      } @@ -119,9 +124,6 @@ public class SQLiteQueryBuilder          if (mWhereClause == null) {              mWhereClause = new StringBuilder(inWhere.length() + 16);          } -        if (mWhereClause.length() == 0) { -            mWhereClause.append('('); -        }          DatabaseUtils.appendEscapedSQLString(mWhereClause, inWhere);      } @@ -380,6 +382,11 @@ public class SQLiteQueryBuilder              return null;          } +        final String sql; +        final String unwrappedSql = buildQuery( +                projectionIn, selection, groupBy, having, +                sortOrder, limit); +          if (mStrict && selection != null && selection.length() > 0) {              // Validate the user-supplied selection to detect syntactic anomalies              // in the selection string that could indicate a SQL injection attempt. @@ -388,25 +395,167 @@ public class SQLiteQueryBuilder              // originally specified. An attacker cannot create an expression that              // would escape the SQL expression while maintaining balanced parentheses              // in both the wrapped and original forms. -            String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy, + +            // NOTE: The ordering of the below operations is important; we must +            // execute the wrapped query to ensure the untrusted clause has been +            // fully isolated. + +            // Validate the unwrapped query +            db.validateSql(unwrappedSql, cancellationSignal); // will throw if query is invalid + +            // Execute wrapped query for extra protection +            final String wrappedSql = buildQuery(projectionIn, wrap(selection), groupBy,                      having, sortOrder, limit); -            db.validateSql(sqlForValidation, cancellationSignal); // will throw if query is invalid +            sql = wrappedSql; +        } else { +            // Execute unwrapped query +            sql = unwrappedSql;          } -        String sql = buildQuery( -                projectionIn, selection, groupBy, having, -                sortOrder, limit); - +        final String[] sqlArgs = selectionArgs;          if (Log.isLoggable(TAG, Log.DEBUG)) { -            Log.d(TAG, "Performing query: " + sql); +            if (Build.IS_DEBUGGABLE) { +                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); +            } else { +                Log.d(TAG, sql); +            }          }          return db.rawQueryWithFactory( -                mFactory, sql, selectionArgs, +                mFactory, sql, sqlArgs,                  SQLiteDatabase.findEditTable(mTables),                  cancellationSignal); // will throw if query is invalid      }      /** +     * Perform an update by combining all current settings and the +     * information passed into this method. +     * +     * @param db the database to update on +     * @param selection A filter declaring which rows to return, +     *   formatted as an SQL WHERE clause (excluding the WHERE +     *   itself). Passing null will return all rows for the given URL. +     * @param selectionArgs You may include ?s in selection, which +     *   will be replaced by the values from selectionArgs, in order +     *   that they appear in the selection. The values will be bound +     *   as Strings. +     * @return the number of rows updated +     * @hide +     */ +    public int update(@NonNull SQLiteDatabase db, @NonNull ContentValues values, +            @Nullable String selection, @Nullable String[] selectionArgs) { +        Objects.requireNonNull(mTables, "No tables defined"); +        Objects.requireNonNull(db, "No database defined"); +        Objects.requireNonNull(values, "No values defined"); + +        final String sql; +        final String unwrappedSql = buildUpdate(values, selection); + +        if (mStrict) { +            // Validate the user-supplied selection to detect syntactic anomalies +            // in the selection string that could indicate a SQL injection attempt. +            // The idea is to ensure that the selection clause is a valid SQL expression +            // by compiling it twice: once wrapped in parentheses and once as +            // originally specified. An attacker cannot create an expression that +            // would escape the SQL expression while maintaining balanced parentheses +            // in both the wrapped and original forms. + +            // NOTE: The ordering of the below operations is important; we must +            // execute the wrapped query to ensure the untrusted clause has been +            // fully isolated. + +            // Validate the unwrapped query +            db.validateSql(unwrappedSql, null); // will throw if query is invalid + +            // Execute wrapped query for extra protection +            final String wrappedSql = buildUpdate(values, wrap(selection)); +            sql = wrappedSql; +        } else { +            // Execute unwrapped query +            sql = unwrappedSql; +        } + +        if (selectionArgs == null) { +            selectionArgs = EmptyArray.STRING; +        } +        final String[] rawKeys = values.keySet().toArray(EmptyArray.STRING); +        final int valuesLength = rawKeys.length; +        final Object[] sqlArgs = new Object[valuesLength + selectionArgs.length]; +        for (int i = 0; i < sqlArgs.length; i++) { +            if (i < valuesLength) { +                sqlArgs[i] = values.get(rawKeys[i]); +            } else { +                sqlArgs[i] = selectionArgs[i - valuesLength]; +            } +        } +        if (Log.isLoggable(TAG, Log.DEBUG)) { +            if (Build.IS_DEBUGGABLE) { +                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); +            } else { +                Log.d(TAG, sql); +            } +        } +        return db.executeSql(sql, sqlArgs); +    } + +    /** +     * Perform a delete by combining all current settings and the +     * information passed into this method. +     * +     * @param db the database to delete on +     * @param selection A filter declaring which rows to return, +     *   formatted as an SQL WHERE clause (excluding the WHERE +     *   itself). Passing null will return all rows for the given URL. +     * @param selectionArgs You may include ?s in selection, which +     *   will be replaced by the values from selectionArgs, in order +     *   that they appear in the selection. The values will be bound +     *   as Strings. +     * @return the number of rows deleted +     * @hide +     */ +    public int delete(@NonNull SQLiteDatabase db, @Nullable String selection, +            @Nullable String[] selectionArgs) { +        Objects.requireNonNull(mTables, "No tables defined"); +        Objects.requireNonNull(db, "No database defined"); + +        final String sql; +        final String unwrappedSql = buildDelete(selection); + +        if (mStrict) { +            // Validate the user-supplied selection to detect syntactic anomalies +            // in the selection string that could indicate a SQL injection attempt. +            // The idea is to ensure that the selection clause is a valid SQL expression +            // by compiling it twice: once wrapped in parentheses and once as +            // originally specified. An attacker cannot create an expression that +            // would escape the SQL expression while maintaining balanced parentheses +            // in both the wrapped and original forms. + +            // NOTE: The ordering of the below operations is important; we must +            // execute the wrapped query to ensure the untrusted clause has been +            // fully isolated. + +            // Validate the unwrapped query +            db.validateSql(unwrappedSql, null); // will throw if query is invalid + +            // Execute wrapped query for extra protection +            final String wrappedSql = buildDelete(wrap(selection)); +            sql = wrappedSql; +        } else { +            // Execute unwrapped query +            sql = unwrappedSql; +        } + +        final String[] sqlArgs = selectionArgs; +        if (Log.isLoggable(TAG, Log.DEBUG)) { +            if (Build.IS_DEBUGGABLE) { +                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs)); +            } else { +                Log.d(TAG, sql); +            } +        } +        return db.executeSql(sql, sqlArgs); +    } + +    /**       * Construct a SELECT statement suitable for use in a group of       * SELECT statements that will be joined through UNION operators       * in buildUnionQuery. @@ -438,28 +587,10 @@ public class SQLiteQueryBuilder              String[] projectionIn, String selection, String groupBy,              String having, String sortOrder, String limit) {          String[] projection = computeProjection(projectionIn); - -        StringBuilder where = new StringBuilder(); -        boolean hasBaseWhereClause = mWhereClause != null && mWhereClause.length() > 0; - -        if (hasBaseWhereClause) { -            where.append(mWhereClause.toString()); -            where.append(')'); -        } - -        // Tack on the user's selection, if present. -        if (selection != null && selection.length() > 0) { -            if (hasBaseWhereClause) { -                where.append(" AND "); -            } - -            where.append('('); -            where.append(selection); -            where.append(')'); -        } +        String where = computeWhere(selection);          return buildQueryString( -                mDistinct, mTables, projection, where.toString(), +                mDistinct, mTables, projection, where,                  groupBy, having, sortOrder, limit);      } @@ -476,6 +607,42 @@ public class SQLiteQueryBuilder          return buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);      } +    /** {@hide} */ +    public String buildUpdate(ContentValues values, String selection) { +        if (values == null || values.size() == 0) { +            throw new IllegalArgumentException("Empty values"); +        } + +        StringBuilder sql = new StringBuilder(120); +        sql.append("UPDATE "); +        sql.append(mTables); +        sql.append(" SET "); + +        final String[] rawKeys = values.keySet().toArray(EmptyArray.STRING); +        for (int i = 0; i < rawKeys.length; i++) { +            if (i > 0) { +                sql.append(','); +            } +            sql.append(rawKeys[i]); +            sql.append("=?"); +        } + +        final String where = computeWhere(selection); +        appendClause(sql, " WHERE ", where); +        return sql.toString(); +    } + +    /** {@hide} */ +    public String buildDelete(String selection) { +        StringBuilder sql = new StringBuilder(120); +        sql.append("DELETE FROM "); +        sql.append(mTables); + +        final String where = computeWhere(selection); +        appendClause(sql, " WHERE ", where); +        return sql.toString(); +    } +      /**       * Construct a SELECT statement suitable for use in a group of       * SELECT statements that will be joined through UNION operators @@ -650,4 +817,37 @@ public class SQLiteQueryBuilder          }          return null;      } + +    private @Nullable String computeWhere(@Nullable String selection) { +        final boolean hasInternal = !TextUtils.isEmpty(mWhereClause); +        final boolean hasExternal = !TextUtils.isEmpty(selection); + +        if (hasInternal || hasExternal) { +            final StringBuilder where = new StringBuilder(); +            if (hasInternal) { +                where.append('(').append(mWhereClause).append(')'); +            } +            if (hasInternal && hasExternal) { +                where.append(" AND "); +            } +            if (hasExternal) { +                where.append('(').append(selection).append(')'); +            } +            return where.toString(); +        } else { +            return null; +        } +    } + +    /** +     * Wrap given argument in parenthesis, unless it's {@code null} or +     * {@code ()}, in which case return it verbatim. +     */ +    private @Nullable String wrap(@Nullable String arg) { +        if (TextUtils.isEmpty(arg)) { +            return arg; +        } else { +            return "(" + arg + ")"; +        } +    }  } diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 9b18e9a12969..35584ae21869 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -1255,7 +1255,9 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri       * <p>If this device is the largest or only camera device with a given facing, then this       * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm       * from the main sensor along the +X axis (to the right from the user's perspective) will -     * report <code>(0.03, 0, 0)</code>.</p> +     * report <code>(0.03, 0, 0)</code>.  Note that this means that, for many computer vision +     * applications, the position needs to be negated to convert it to a translation from the +     * camera to the origin.</p>       * <p>To transform a pixel coordinates between two cameras facing the same direction, first       * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for.  Then the source       * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the @@ -1267,7 +1269,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri       * <p>To compare this against a real image from the destination camera, the destination camera       * image then needs to be corrected for radial distortion before comparison or sampling.</p>       * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to -     * the center of the primary gyroscope on the device.</p> +     * the center of the primary gyroscope on the device. The axis definitions are the same as +     * with PRIMARY_CAMERA.</p>       * <p><b>Units</b>: Meters</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * @@ -1299,13 +1302,15 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri       * </code></pre>       * <p>which can then be combined with the camera pose rotation       * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and -     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the +     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the       * complete transform from world coordinates to pixel       * coordinates:</p> -     * <pre><code>P = [ K 0   * [ R t -     *      0 1 ]     0 1 ] +     * <pre><code>P = [ K 0   * [ R -Rt +     *      0 1 ]      0 1 ]       * </code></pre> -     * <p>and with <code>p_w</code> being a point in the world coordinate system +     * <p>(Note the negation of poseTranslation when mapping from camera +     * to world coordinates, and multiplication by the rotation).</p> +     * <p>With <code>p_w</code> being a point in the world coordinate system       * and <code>p_s</code> being a point in the camera active pixel array       * coordinate system, and with the mapping including the       * homogeneous division by z:</p> @@ -1327,6 +1332,13 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri       * activeArraySize rectangle), to determine the final pixel       * coordinate of the world point for processed (non-RAW)       * output buffers.</p> +     * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at +     * coordinate <code>(x + 0.5, y + 0.5)</code>.  So on a device with a +     * precorrection active array of size <code>(10,10)</code>, the valid pixel +     * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would +     * have an optical center at the exact center of the pixel grid, at +     * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel +     * <code>(5,5)</code>.</p>       * <p><b>Units</b>:       * Pixels in the       * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 1275a852ee2b..caa99d5cb2a8 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -819,11 +819,11 @@ public abstract class CameraMetadata<TKey> {       * camera in the list of supported camera devices.</p>       * <p>This capability requires the camera device to support the following:</p>       * <ul> -     * <li>This camera device must list the following static metadata entries in {@link android.hardware.camera2.CameraCharacteristics }:<ul> -     * <li>android.logicalMultiCamera.physicalIds</li> -     * <li>{@link CameraCharacteristics#LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE android.logicalMultiCamera.sensorSyncType}</li> -     * </ul> -     * </li> +     * <li>The IDs of underlying physical cameras are returned via +     *   {@link android.hardware.camera2.CameraCharacteristics#getPhysicalCameraIds }.</li> +     * <li>This camera device must list static metadata +     *   {@link CameraCharacteristics#LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE android.logicalMultiCamera.sensorSyncType} in +     *   {@link android.hardware.camera2.CameraCharacteristics }.</li>       * <li>The underlying physical cameras' static metadata must list the following entries,       *   so that the application can correlate pixels from the physical streams:<ul>       * <li>{@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference}</li> diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 0b92b0cbef15..4a20468276d3 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -2530,7 +2530,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>       * outputs will crop horizontally (pillarbox), and 16:9       * streams will match exactly. These additional crops will       * be centered within the crop region.</p> -     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height +     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height       * of the crop region cannot be set to be smaller than       * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and       * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p> @@ -2871,8 +2871,14 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>              new Key<Integer>("android.statistics.lensShadingMapMode", int.class);      /** -     * <p>A control for selecting whether OIS position information is included in output -     * result metadata.</p> +     * <p>A control for selecting whether optical stabilization (OIS) position +     * information is included in output result metadata.</p> +     * <p>Since optical image stabilization generally involves motion much faster than the duration +     * of individualq image exposure, multiple OIS samples can be included for a single capture +     * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating +     * at 30fps may have 6-7 OIS samples per capture result. This information can be combined +     * with the rolling shutter skew to account for lens motion during image exposure in +     * post-processing algorithms.</p>       * <p><b>Possible values:</b>       * <ul>       *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> @@ -3272,14 +3278,28 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>       * any correction at all would slow down capture rate.  Every output stream will have a       * similar amount of enhancement applied.</p>       * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not -     * applied to any RAW output. Metadata coordinates such as face rectangles or metering -     * regions are also not affected by correction.</p> +     * applied to any RAW output.</p>       * <p>This control will be on by default on devices that support this control. Applications       * disabling distortion correction need to pay extra attention with the coordinate system of       * metering regions, crop region, and face rectangles. When distortion correction is OFF,       * metadata coordinates follow the coordinate system of       * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata -     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> +     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.  The +     * camera device will map these metadata fields to match the corrected image produced by the +     * camera device, for both capture requests and results.  However, this mapping is not very +     * precise, since rectangles do not generally map to rectangles when corrected.  Only linear +     * scaling between the active array and precorrection active array coordinates is +     * performed. Applications that require precise correction of metadata need to undo that +     * linear scaling, and apply a more complete correction that takes into the account the app's +     * own requirements.</p> +     * <p>The full list of metadata that is affected in this way by distortion correction is:</p> +     * <ul> +     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li> +     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li> +     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li> +     * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> +     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> +     * </ul>       * <p><b>Possible values:</b>       * <ul>       *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> @@ -3290,10 +3310,15 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>       * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * +     * @see CaptureRequest#CONTROL_AE_REGIONS +     * @see CaptureRequest#CONTROL_AF_REGIONS +     * @see CaptureRequest#CONTROL_AWB_REGIONS       * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES       * @see CameraCharacteristics#LENS_DISTORTION +     * @see CaptureRequest#SCALER_CROP_REGION       * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE       * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE +     * @see CaptureResult#STATISTICS_FACES       * @see #DISTORTION_CORRECTION_MODE_OFF       * @see #DISTORTION_CORRECTION_MODE_FAST       * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index e007d282ad04..1e894e8a29c2 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -2858,7 +2858,9 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * <p>If this device is the largest or only camera device with a given facing, then this       * position will be <code>(0, 0, 0)</code>; a camera device with a lens optical center located 3 cm       * from the main sensor along the +X axis (to the right from the user's perspective) will -     * report <code>(0.03, 0, 0)</code>.</p> +     * report <code>(0.03, 0, 0)</code>.  Note that this means that, for many computer vision +     * applications, the position needs to be negated to convert it to a translation from the +     * camera to the origin.</p>       * <p>To transform a pixel coordinates between two cameras facing the same direction, first       * the source camera {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} must be corrected for.  Then the source       * camera {@link CameraCharacteristics#LENS_INTRINSIC_CALIBRATION android.lens.intrinsicCalibration} needs to be applied, followed by the @@ -2870,7 +2872,8 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * <p>To compare this against a real image from the destination camera, the destination camera       * image then needs to be corrected for radial distortion before comparison or sampling.</p>       * <p>When {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} is GYROSCOPE, then this position is relative to -     * the center of the primary gyroscope on the device.</p> +     * the center of the primary gyroscope on the device. The axis definitions are the same as +     * with PRIMARY_CAMERA.</p>       * <p><b>Units</b>: Meters</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * @@ -2902,13 +2905,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * </code></pre>       * <p>which can then be combined with the camera pose rotation       * <code>R</code> and translation <code>t</code> ({@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation} and -     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respective) to calculate the +     * {@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}, respectively) to calculate the       * complete transform from world coordinates to pixel       * coordinates:</p> -     * <pre><code>P = [ K 0   * [ R t -     *      0 1 ]     0 1 ] +     * <pre><code>P = [ K 0   * [ R -Rt +     *      0 1 ]      0 1 ]       * </code></pre> -     * <p>and with <code>p_w</code> being a point in the world coordinate system +     * <p>(Note the negation of poseTranslation when mapping from camera +     * to world coordinates, and multiplication by the rotation).</p> +     * <p>With <code>p_w</code> being a point in the world coordinate system       * and <code>p_s</code> being a point in the camera active pixel array       * coordinate system, and with the mapping including the       * homogeneous division by z:</p> @@ -2930,6 +2935,13 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * activeArraySize rectangle), to determine the final pixel       * coordinate of the world point for processed (non-RAW)       * output buffers.</p> +     * <p>For camera devices, the center of pixel <code>(x,y)</code> is located at +     * coordinate <code>(x + 0.5, y + 0.5)</code>.  So on a device with a +     * precorrection active array of size <code>(10,10)</code>, the valid pixel +     * indices go from <code>(0,0)-(9,9)</code>, and an perfectly-built camera would +     * have an optical center at the exact center of the pixel grid, at +     * coordinates <code>(5.0, 5.0)</code>, which is the top-left corner of pixel +     * <code>(5,5)</code>.</p>       * <p><b>Units</b>:       * Pixels in the       * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} @@ -3194,7 +3206,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * outputs will crop horizontally (pillarbox), and 16:9       * streams will match exactly. These additional crops will       * be centered within the crop region.</p> -     * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height +     * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, the width and height       * of the crop region cannot be set to be smaller than       * <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and       * <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p> @@ -4083,8 +4095,14 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {              new Key<Integer>("android.statistics.lensShadingMapMode", int.class);      /** -     * <p>A control for selecting whether OIS position information is included in output -     * result metadata.</p> +     * <p>A control for selecting whether optical stabilization (OIS) position +     * information is included in output result metadata.</p> +     * <p>Since optical image stabilization generally involves motion much faster than the duration +     * of individualq image exposure, multiple OIS samples can be included for a single capture +     * result. For example, if the OIS reporting operates at 200 Hz, a typical camera operating +     * at 30fps may have 6-7 OIS samples per capture result. This information can be combined +     * with the rolling shutter skew to account for lens motion during image exposure in +     * post-processing algorithms.</p>       * <p><b>Possible values:</b>       * <ul>       *   <li>{@link #STATISTICS_OIS_DATA_MODE_OFF OFF}</li> @@ -4118,11 +4136,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {      /**       * <p>An array of shifts of OIS samples, in x direction.</p>       * <p>The array contains the amount of shifts in x direction, in pixels, based on OIS samples. -     * A positive value is a shift from left to right in active array coordinate system. For -     * example, if the optical center is (1000, 500) in active array coordinates, a shift of -     * (3, 0) puts the new optical center at (1003, 500).</p> +     * A positive value is a shift from left to right in the pre-correction active array +     * coordinate system. For example, if the optical center is (1000, 500) in pre-correction +     * active array coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p>       * <p>The number of shifts must match the number of timestamps in       * android.statistics.oisTimestamps.</p> +     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on +     * supporting devices). They are always reported in pre-correction active array coordinates, +     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift +     * is needed.</p>       * <p><b>Units</b>: Pixels in active array.</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * @hide @@ -4133,11 +4155,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {      /**       * <p>An array of shifts of OIS samples, in y direction.</p>       * <p>The array contains the amount of shifts in y direction, in pixels, based on OIS samples. -     * A positive value is a shift from top to bottom in active array coordinate system. For -     * example, if the optical center is (1000, 500) in active array coordinates, a shift of -     * (0, 5) puts the new optical center at (1000, 505).</p> +     * A positive value is a shift from top to bottom in pre-correction active array coordinate +     * system. For example, if the optical center is (1000, 500) in active array coordinates, a +     * shift of (0, 5) puts the new optical center at (1000, 505).</p>       * <p>The number of shifts must match the number of timestamps in       * android.statistics.oisTimestamps.</p> +     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on +     * supporting devices). They are always reported in pre-correction active array coordinates, +     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift +     * is needed.</p>       * <p><b>Units</b>: Pixels in active array.</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * @hide @@ -4146,15 +4172,21 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {              new Key<float[]>("android.statistics.oisYShifts", float[].class);      /** -     * <p>An array of OIS samples.</p> +     * <p>An array of optical stabilization (OIS) position samples.</p>       * <p>Each OIS sample contains the timestamp and the amount of shifts in x and y direction,       * in pixels, of the OIS sample.</p> -     * <p>A positive value for a shift in x direction is a shift from left to right in active array -     * coordinate system. For example, if the optical center is (1000, 500) in active array -     * coordinates, a shift of (3, 0) puts the new optical center at (1003, 500).</p> -     * <p>A positive value for a shift in y direction is a shift from top to bottom in active array -     * coordinate system. For example, if the optical center is (1000, 500) in active array -     * coordinates, a shift of (0, 5) puts the new optical center at (1000, 505).</p> +     * <p>A positive value for a shift in x direction is a shift from left to right in the +     * pre-correction active array coordinate system. For example, if the optical center is +     * (1000, 500) in pre-correction active array coordinates, a shift of (3, 0) puts the new +     * optical center at (1003, 500).</p> +     * <p>A positive value for a shift in y direction is a shift from top to bottom in +     * pre-correction active array coordinate system. For example, if the optical center is +     * (1000, 500) in active array coordinates, a shift of (0, 5) puts the new optical center at +     * (1000, 505).</p> +     * <p>The OIS samples are not affected by whether lens distortion correction is enabled (on +     * supporting devices). They are always reported in pre-correction active array coordinates, +     * since the scaling of OIS shifts would depend on the specific spot on the sensor the shift +     * is needed.</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       */      @PublicKey @@ -4584,14 +4616,28 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * any correction at all would slow down capture rate.  Every output stream will have a       * similar amount of enhancement applied.</p>       * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not -     * applied to any RAW output. Metadata coordinates such as face rectangles or metering -     * regions are also not affected by correction.</p> +     * applied to any RAW output.</p>       * <p>This control will be on by default on devices that support this control. Applications       * disabling distortion correction need to pay extra attention with the coordinate system of       * metering regions, crop region, and face rectangles. When distortion correction is OFF,       * metadata coordinates follow the coordinate system of       * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata -     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> +     * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.  The +     * camera device will map these metadata fields to match the corrected image produced by the +     * camera device, for both capture requests and results.  However, this mapping is not very +     * precise, since rectangles do not generally map to rectangles when corrected.  Only linear +     * scaling between the active array and precorrection active array coordinates is +     * performed. Applications that require precise correction of metadata need to undo that +     * linear scaling, and apply a more complete correction that takes into the account the app's +     * own requirements.</p> +     * <p>The full list of metadata that is affected in this way by distortion correction is:</p> +     * <ul> +     * <li>{@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}</li> +     * <li>{@link CaptureRequest#CONTROL_AE_REGIONS android.control.aeRegions}</li> +     * <li>{@link CaptureRequest#CONTROL_AWB_REGIONS android.control.awbRegions}</li> +     * <li>{@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}</li> +     * <li>{@link CaptureResult#STATISTICS_FACES android.statistics.faces}</li> +     * </ul>       * <p><b>Possible values:</b>       * <ul>       *   <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li> @@ -4602,10 +4648,15 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {       * {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>       * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>       * +     * @see CaptureRequest#CONTROL_AE_REGIONS +     * @see CaptureRequest#CONTROL_AF_REGIONS +     * @see CaptureRequest#CONTROL_AWB_REGIONS       * @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES       * @see CameraCharacteristics#LENS_DISTORTION +     * @see CaptureRequest#SCALER_CROP_REGION       * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE       * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE +     * @see CaptureResult#STATISTICS_FACES       * @see #DISTORTION_CORRECTION_MODE_OFF       * @see #DISTORTION_CORRECTION_MODE_FAST       * @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 1b22911f0cdc..22dd4fc362ba 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -333,6 +333,14 @@ public class TrafficStats {      /**       * Remove any statistics parameters from the given {@link Socket}. +     * <p> +     * In Android 8.1 (API level 27) and lower, a socket is automatically +     * untagged when it's sent to another process using binder IPC with a +     * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28) +     * and higher, the socket tag is kept when the socket is sent to another +     * process using binder IPC. You can mimic the previous behavior by +     * calling {@code untagSocket()} before sending the socket to another +     * process.       */      public static void untagSocket(Socket socket) throws SocketException {          SocketTagger.get().untag(socket); diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 91888949829f..68b6d722f345 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -628,7 +628,8 @@ public class Build {           * October 2013: Android 4.4, KitKat, another tasty treat.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see the +         * <a href="/about/versions/kitkat/">Android KitKat overview</a>.</p>           * <ul>           * <li> The default result of           * {@link android.preference.PreferenceActivity#isValidFragment(String) @@ -678,7 +679,8 @@ public class Build {           * November 2014: Lollipop.  A flat one with beautiful shadows.  But still tasty.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior.  For more information about this release, see the +         * <a href="/about/versions/lollipop/">Android Lollipop overview</a>.</p>           * <ul>           * <li> {@link android.content.Context#bindService Context.bindService} now           * requires an explicit Intent, and will throw an exception if given an implicit @@ -707,6 +709,8 @@ public class Build {          /**           * March 2015: Lollipop with an extra sugar coating on the outside! +         * For more information about this release, see the +         * <a href="/about/versions/android-5.1">Android 5.1 APIs</a>.           */          public static final int LOLLIPOP_MR1 = 22; @@ -714,7 +718,8 @@ public class Build {           * M is for Marshmallow!           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see the +         * <a href="/about/versions/marshmallow/">Android 6.0 Marshmallow overview</a>.</p>           * <ul>           * <li> Runtime permissions.  Dangerous permissions are no longer granted at           * install time, but must be requested by the application at runtime through @@ -745,7 +750,8 @@ public class Build {           * N is for Nougat.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see +         * the <a href="/about/versions/nougat/">Android Nougat overview</a>.</p>           * <ul>           * <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes           * DownloadManager.Request.setAllowedNetworkTypes} @@ -795,7 +801,9 @@ public class Build {          public static final int N = 24;          /** -         * N MR1: Nougat++. +         * N MR1: Nougat++. For more information about this release, see +         * <a href="/about/versions/nougat/android-7.1">Android 7.1 for +         * Developers</a>.           */          public static final int N_MR1 = 25; @@ -803,7 +811,8 @@ public class Build {           * O.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see +         * the <a href="/about/versions/oreo/">Android Oreo overview</a>.</p>           * <ul>           * <li><a href="{@docRoot}about/versions/oreo/background.html">Background execution limits</a>           * are applied to the application.</li> @@ -892,13 +901,16 @@ public class Build {           * O MR1.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see +         * <a href="/about/versions/oreo/android-8.1">Android 8.1 features and +         * APIs</a>.</p>           * <ul>           * <li>Apps exporting and linking to apk shared libraries must explicitly           * enumerate all signing certificates in a consistent order.</li>           * <li>{@link android.R.attr#screenOrientation} can not be used to request a fixed           * orientation if the associated activity is not fullscreen and opaque.</li>           * </ul> +         *           */          public static final int O_MR1 = 27; @@ -906,7 +918,8 @@ public class Build {           * P.           *           * <p>Applications targeting this or a later release will get these -         * new changes in behavior:</p> +         * new changes in behavior. For more information about this release, see the +         * <a href="/about/versions/pie/">Android 9 Pie overview</a>.</p>           * <ul>           * <li>{@link android.app.Service#startForeground Service.startForeground} requires           * that apps hold the permission @@ -914,6 +927,7 @@ public class Build {           * <li>{@link android.widget.LinearLayout} will always remeasure weighted children,           * even if there is no excess space.</li>           * </ul> +         *           */          public static final int P = 28; diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java index b303e10fa64b..455d8edd4138 100644 --- a/core/java/android/os/Message.java +++ b/core/java/android/os/Message.java @@ -349,7 +349,7 @@ public final class Message implements Parcelable {      }      /** -     * Retrieve the a {@link android.os.Handler Handler} implementation that +     * Retrieve the {@link android.os.Handler Handler} implementation that       * will receive this message. The object must implement       * {@link android.os.Handler#handleMessage(android.os.Message)       * Handler.handleMessage()}. Each Handler has its own name-space for diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java index d4d3dc838d91..7b3ea57ba0e9 100644 --- a/core/java/android/os/StatsLogEventWrapper.java +++ b/core/java/android/os/StatsLogEventWrapper.java @@ -65,11 +65,17 @@ public final class StatsLogEventWrapper implements Parcelable {      public static final Parcelable.Creator<StatsLogEventWrapper> CREATOR = new              Parcelable.Creator<StatsLogEventWrapper>() {                  public StatsLogEventWrapper createFromParcel(Parcel in) { -                    return new StatsLogEventWrapper(in); +                    android.util.EventLog.writeEvent(0x534e4554, "112550251", +                            android.os.Binder.getCallingUid(), ""); +                    // Purposefully leaving this method not implemented. +                    throw new RuntimeException("Not implemented");                  }                  public StatsLogEventWrapper[] newArray(int size) { -                    return new StatsLogEventWrapper[size]; +                    android.util.EventLog.writeEvent(0x534e4554, "112550251", +                            android.os.Binder.getCallingUid(), ""); +                    // Purposefully leaving this method not implemented. +                    throw new RuntimeException("Not implemented");                  }              }; @@ -120,10 +126,6 @@ public final class StatsLogEventWrapper implements Parcelable {          mStorage.write(bytes, 0, bytes.length);      } -    private StatsLogEventWrapper(Parcel in) { -        readFromParcel(in); -    } -      /**       * Writes the stored fields to a byte array. Will first write a new-line character to denote       * END_LIST before writing contents to byte array. @@ -134,13 +136,6 @@ public final class StatsLogEventWrapper implements Parcelable {      }      /** -     * Not implemented. -     */ -    public void readFromParcel(Parcel in) { -        // Not needed since this java class is for sending to statsd only. -    } - -    /**       * Boilerplate for Parcel.       */      public int describeContents() { diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index d16390976d1f..8ed2605e9e8c 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -80,7 +80,7 @@ import java.util.List;   * <li>On a small screen it may display only the headers as a single list when first launched.   * Selecting one of the header items will only show the PreferenceFragment of that header (on   * Android N and lower a new Activity is launched). - * <li>On a large screen in may display both the headers and current PreferenceFragment together as + * <li>On a large screen it may display both the headers and current PreferenceFragment together as   * panes. Selecting a header item switches to showing the correct PreferenceFragment for that item.   * </ul>   * diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6f6a9be5b909..1817972981e9 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10618,6 +10618,15 @@ public final class Settings {          public static final String ACTIVITY_MANAGER_CONSTANTS = "activity_manager_constants";          /** +         * Feature flag to enable or disable the activity starts logging feature. +         * Type: int (0 for false, 1 for true) +         * Default: 0 +         * @hide +         */ +        public static final String ACTIVITY_STARTS_LOGGING_ENABLED +                = "activity_starts_logging_enabled"; + +        /**           * App ops specific settings.           * This is encoded as a key=value list, separated by commas. Ex:           * diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index 521176797657..f8408bedd7bc 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -33,8 +33,13 @@ import java.util.ArrayList;  import java.util.regex.Pattern;  /** - * A dataset object represents a group of fields (key / value pairs) used to autofill parts of a - * screen. + * <p>A <code>Dataset</code> object represents a group of fields (key / value pairs) used + * to autofill parts of a screen. + * + * <p>For more information about the role of datasets in the autofill workflow, read + * <a href="/guide/topics/text/autofill-services">Build autofill services</a> and the + * <code><a href="/reference/android/service/autofill/AutofillService">AutofillService</a></code> + * documentation.   *   * <a name="BasicUsage"></a>   * <h3>Basic usage</h3> @@ -88,10 +93,6 @@ import java.util.regex.Pattern;   *   <li>All other datasets are hidden.   * </ol>   * - * <a name="MoreInfo"></a> - * <h3>More information</h3> - * <p>See {@link android.service.autofill.AutofillService} for more information and examples about - * the role of datasets in the autofill workflow.   */  public final class Dataset implements Parcelable { diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java index 0257891e5f38..1695c1306824 100644 --- a/core/java/android/service/autofill/FillCallback.java +++ b/core/java/android/service/autofill/FillCallback.java @@ -21,8 +21,11 @@ import android.app.Activity;  import android.os.RemoteException;  /** - * Handles autofill requests from the {@link AutofillService} into the {@link Activity} being - * autofilled. + * <p><code>FillCallback</code> handles autofill requests from the {@link AutofillService} into + * the {@link Activity} being autofilled. + * + * <p>To learn about using Autofill services in your app, read + * <a href="/guide/topics/text/autofill-services">Build autofill services</a>.   */  public final class FillCallback {      private final IFillCallback mCallback; diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java index b6c6bdc00bbe..5a7a83f19b0c 100644 --- a/core/java/android/service/notification/Condition.java +++ b/core/java/android/service/notification/Condition.java @@ -151,14 +151,14 @@ public final class Condition implements Parcelable {      @Override      public String toString() {          return new StringBuilder(Condition.class.getSimpleName()).append('[') -            .append("id=").append(id) -            .append(",summary=").append(summary) -            .append(",line1=").append(line1) -            .append(",line2=").append(line2) -            .append(",icon=").append(icon) -            .append(",state=").append(stateToString(state)) -            .append(",flags=").append(flags) -            .append(']').toString(); +                .append("state=").append(stateToString(state)) +                .append(",id=").append(id) +                .append(",summary=").append(summary) +                .append(",line1=").append(line1) +                .append(",line2=").append(line2) +                .append(",icon=").append(icon) +                .append(",flags=").append(flags) +                .append(']').toString();      }      /** @hide */ diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index f6749ee66bb4..1af2e73c95ce 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -244,11 +244,29 @@ public class ZenModeConfig implements Parcelable {                  .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))                  .append(",suppressedVisualEffects=").append(suppressedVisualEffects)                  .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd) -                .append(",automaticRules=").append(automaticRules) -                .append(",manualRule=").append(manualRule) +                .append(",\nautomaticRules=").append(rulesToString()) +                .append(",\nmanualRule=").append(manualRule)                  .append(']').toString();      } +    private String rulesToString() { +        if (automaticRules.isEmpty()) { +            return "{}"; +        } + +        StringBuilder buffer = new StringBuilder(automaticRules.size() * 28); +        buffer.append('{'); +        for (int i = 0; i < automaticRules.size(); i++) { +            if (i > 0) { +                buffer.append(",\n"); +            } +            Object value = automaticRules.valueAt(i); +            buffer.append(value); +        } +        buffer.append('}'); +        return buffer.toString(); +    } +      private Diff diff(ZenModeConfig to) {          final Diff d = new Diff();          if (to == null) { @@ -1014,10 +1032,10 @@ public class ZenModeConfig implements Parcelable {      @UnsupportedAppUsage      public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {          final boolean isSchedule =  conditionId != null -                && conditionId.getScheme().equals(Condition.SCHEME) -                && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) +                && Condition.SCHEME.equals(conditionId.getScheme()) +                && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority())                  && conditionId.getPathSegments().size() == 1 -                && conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH); +                && ZenModeConfig.SCHEDULE_PATH.equals(conditionId.getPathSegments().get(0));          if (!isSchedule) return null;          final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start"));          final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end")); @@ -1120,10 +1138,10 @@ public class ZenModeConfig implements Parcelable {      public static EventInfo tryParseEventConditionId(Uri conditionId) {          final boolean isEvent = conditionId != null -                && conditionId.getScheme().equals(Condition.SCHEME) -                && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY) +                && Condition.SCHEME.equals(conditionId.getScheme()) +                && ZenModeConfig.SYSTEM_AUTHORITY.equals(conditionId.getAuthority())                  && conditionId.getPathSegments().size() == 1 -                && conditionId.getPathSegments().get(0).equals(EVENT_PATH); +                && EVENT_PATH.equals(conditionId.getPathSegments().get(0));          if (!isEvent) return null;          final EventInfo rt = new EventInfo();          rt.userId = tryParseInt(conditionId.getQueryParameter("userId"), UserHandle.USER_NULL); @@ -1338,14 +1356,14 @@ public class ZenModeConfig implements Parcelable {          @Override          public String toString() {              return new StringBuilder(ZenRule.class.getSimpleName()).append('[') -                    .append("enabled=").append(enabled) +                    .append("id=").append(id) +                    .append(",enabled=").append(String.valueOf(enabled).toUpperCase())                      .append(",snoozing=").append(snoozing)                      .append(",name=").append(name)                      .append(",zenMode=").append(Global.zenModeToString(zenMode))                      .append(",conditionId=").append(conditionId)                      .append(",condition=").append(condition)                      .append(",component=").append(component) -                    .append(",id=").append(id)                      .append(",creationTime=").append(creationTime)                      .append(",enabler=").append(enabler)                      .append(']').toString(); @@ -1477,7 +1495,7 @@ public class ZenModeConfig implements Parcelable {              final int N = lines.size();              for (int i = 0; i < N; i++) {                  if (i > 0) { -                    sb.append(','); +                    sb.append(",\n");                  }                  sb.append(lines.get(i));              } diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 3afa3252c5a3..8a49c2859d1b 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1590,7 +1590,8 @@ public abstract class Layout {          }          float get(final int offset) { -            if (mHorizontals == null) { +            if (mHorizontals == null || offset < mLineStartOffset +                    || offset >= mLineStartOffset + mHorizontals.length) {                  return getHorizontal(offset, mPrimary);              } else {                  return mHorizontals[offset - mLineStartOffset]; diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java index dc07494b15db..aa5ca3530621 100644 --- a/core/java/android/util/SparseArray.java +++ b/core/java/android/util/SparseArray.java @@ -23,32 +23,34 @@ import android.annotation.UnsupportedAppUsage;  import libcore.util.EmptyArray;  /** - * SparseArrays map integers to Objects.  Unlike a normal array of Objects, - * there can be gaps in the indices.  It is intended to be more memory efficient - * than using a HashMap to map Integers to Objects, both because it avoids + * <code>SparseArray</code> maps integers to Objects and, unlike a normal array of Objects, + * its indices can contain gaps. <code>SparseArray</code> is intended to be more memory-efficient + * than a + * <a href="/reference/java/util/HashMap"><code>HashMap</code></a>, because it avoids   * auto-boxing keys and its data structure doesn't rely on an extra entry object   * for each mapping.   *   * <p>Note that this container keeps its mappings in an array data structure, - * using a binary search to find keys.  The implementation is not intended to be appropriate for + * using a binary search to find keys. The implementation is not intended to be appropriate for   * data structures - * that may contain large numbers of items.  It is generally slower than a traditional - * HashMap, since lookups require a binary search and adds and removes require inserting - * and deleting entries in the array.  For containers holding up to hundreds of items, - * the performance difference is not significant, less than 50%.</p> + * that may contain large numbers of items. It is generally slower than a + * <code>HashMap</code> because lookups require a binary search, + * and adds and removes require inserting + * and deleting entries in the array. For containers holding up to hundreds of items, + * the performance difference is less than 50%.   *   * <p>To help with performance, the container includes an optimization when removing   * keys: instead of compacting its array immediately, it leaves the removed entry marked - * as deleted.  The entry can then be re-used for the same key, or compacted later in - * a single garbage collection step of all removed entries.  This garbage collection will - * need to be performed at any time the array needs to be grown or the the map size or - * entry values are retrieved.</p> + * as deleted. The entry can then be re-used for the same key or compacted later in + * a single garbage collection of all removed entries. This garbage collection + * must be performed whenever the array needs to be grown, or when the map size or + * entry values are retrieved.   *   * <p>It is possible to iterate over the items in this container using   * {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using - * <code>keyAt(int)</code> with ascending values of the index will return the - * keys in ascending order, or the values corresponding to the keys in ascending - * order in the case of <code>valueAt(int)</code>.</p> + * <code>keyAt(int)</code> with ascending values of the index returns the + * keys in ascending order. In the case of <code>valueAt(int)</code>, the + * values corresponding to the keys are returned in ascending order.   */  public class SparseArray<E> implements Cloneable {      private static final Object DELETED = new Object(); @@ -337,7 +339,7 @@ public class SparseArray<E> implements Cloneable {      /**       * Returns an index for which {@link #valueAt} would return the -     * specified key, or a negative number if no keys map to the +     * specified value, or a negative number if no keys map to the       * specified value.       * <p>Beware that this is a linear search, unlike lookups by key,       * and that multiple keys can map to the same value and this will @@ -361,7 +363,7 @@ public class SparseArray<E> implements Cloneable {      /**       * Returns an index for which {@link #valueAt} would return the -     * specified key, or a negative number if no keys map to the +     * specified value, or a negative number if no keys map to the       * specified value.       * <p>Beware that this is a linear search, unlike lookups by key,       * and that multiple keys can map to the same value and this will diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 496bc9ff5383..5f80d31651a8 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -325,6 +325,7 @@ public final class DisplayCutout {       *       * @hide       */ +    @VisibleForTesting      public static DisplayCutout fromBoundingRect(int left, int top, int right, int bottom) {          Region r = Region.obtain();          r.set(left, top, right, bottom); @@ -422,8 +423,11 @@ public final class DisplayCutout {          m.postTranslate(offsetX, 0);          p.transform(m); -        addToRegion(p, r); +        final Rect tmpRect = new Rect(); +        toRectAndAddToRegion(p, r, tmpRect); +        final int topInset = tmpRect.bottom; +        final int bottomInset;          if (bottomSpec != null) {              final Path bottomPath;              try { @@ -436,10 +440,17 @@ public final class DisplayCutout {              m.postTranslate(0, displayHeight);              bottomPath.transform(m);              p.addPath(bottomPath); -            addToRegion(bottomPath, r); +            toRectAndAddToRegion(bottomPath, r, tmpRect); +            bottomInset = displayHeight - tmpRect.top; +        } else { +            bottomInset = 0;          } -        final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(r)); +        // Reuse tmpRect as the inset rect we store into the DisplayCutout instance. +        tmpRect.set(0, topInset, 0, bottomInset); +        final DisplayCutout cutout = new DisplayCutout(tmpRect, r, false /* copyArguments */); + +        final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout);          synchronized (CACHE_LOCK) {              sCachedSpec = spec;              sCachedDisplayWidth = displayWidth; @@ -450,12 +461,11 @@ public final class DisplayCutout {          return result;      } -    private static void addToRegion(Path p, Region r) { +    private static void toRectAndAddToRegion(Path p, Region inoutRegion, Rect inoutRect) {          final RectF rectF = new RectF(); -        final Rect rect = new Rect();          p.computeBounds(rectF, false /* unused */); -        rectF.round(rect); -        r.op(rect, Op.UNION); +        rectF.round(inoutRect); +        inoutRegion.op(inoutRect, Op.UNION);      }      private static Region boundingRectsToRegion(List<Rect> rects) { diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java index 3f7ab2aed4af..38dcdd30d843 100644 --- a/core/java/android/view/ViewStructure.java +++ b/core/java/android/view/ViewStructure.java @@ -33,9 +33,14 @@ import com.android.internal.util.Preconditions;  import java.util.List;  /** - * Container for storing additional per-view data generated by {@link View#onProvideStructure + * <p><code>ViewStructure</code> is a container for storing additional + * per-view data generated by {@link View#onProvideStructure   * View.onProvideStructure} and {@link View#onProvideAutofillStructure   * View.onProvideAutofillStructure}. + * + * <p>To learn more about using Autofill in your app, read the + * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides. + *   */  public abstract class ViewStructure { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 8b9b85651e7e..84a460119726 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1699,6 +1699,15 @@ public interface WindowManager extends ViewManager {          public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000;          /** +         * Flag to indicate that the status bar window is now in an explicit expanded state, meaning +         * that status bar will not be hidden by any window with flag {@link #FLAG_FULLSCREEN} or +         * {@link View#SYSTEM_UI_FLAG_FULLSCREEN} set. +         * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. +         * @hide +         */ +        public static final int PRIVATE_FLAG_STATUS_BAR_EXPANDED = 0x00800000; + +        /**           * Control flags that are private to the platform.           * @hide           */ @@ -1786,7 +1795,11 @@ public interface WindowManager extends ViewManager {                  @ViewDebug.FlagToString(                          mask = PRIVATE_FLAG_IS_SCREEN_DECOR,                          equals = PRIVATE_FLAG_IS_SCREEN_DECOR, -                        name = "IS_SCREEN_DECOR") +                        name = "IS_SCREEN_DECOR"), +                @ViewDebug.FlagToString( +                        mask = PRIVATE_FLAG_STATUS_BAR_EXPANDED, +                        equals = PRIVATE_FLAG_STATUS_BAR_EXPANDED, +                        name = "STATUS_BAR_EXPANDED")          })          @TestApi          public int privateFlags; diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java index 769ea3e1d2c4..b382a1863af3 100644 --- a/core/java/android/view/accessibility/AccessibilityRecord.java +++ b/core/java/android/view/accessibility/AccessibilityRecord.java @@ -628,7 +628,7 @@ public class AccessibilityRecord {      }      /** -     * Sets the text before a change. +     * Gets the text before a change.       *       * @return The text before the change.       */ diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 7555ffff3e38..d21cb3e64b8c 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -77,11 +77,16 @@ import java.util.Objects;  import sun.misc.Cleaner;  /** - * The {@link AutofillManager} provides ways for apps and custom views to integrate with the - * Autofill Framework lifecycle. + * <p>The {@link AutofillManager} class provides ways for apps and custom views to + * integrate with the Autofill Framework lifecycle. + * + * <p>To learn about using Autofill in your app, read + * the <a href="/guide/topics/text/autofill">Autofill Framework</a> guides. + * + * <h3 id="autofill-lifecycle">Autofill lifecycle</h3>   *   * <p>The autofill lifecycle starts with the creation of an autofill context associated with an - * activity context; the autofill context is created when one of the following methods is called for + * activity context. The autofill context is created when one of the following methods is called for   * the first time in an activity context, and the current user has an enabled autofill service:   *   * <ul> @@ -90,7 +95,7 @@ import sun.misc.Cleaner;   *   <li>{@link #requestAutofill(View)}   * </ul>   * - * <p>Tipically, the context is automatically created when the first view of the activity is + * <p>Typically, the context is automatically created when the first view of the activity is   * focused because {@code View.onFocusChanged()} indirectly calls   * {@link #notifyViewEntered(View)}. App developers can call {@link #requestAutofill(View)} to   * explicitly create it (for example, a custom view developer could offer a contextual menu action @@ -134,7 +139,9 @@ import sun.misc.Cleaner;   * shows an autofill save UI if the value of savable views have changed. If the user selects the   * option to Save, the current value of the views is then sent to the autofill service.   * - * <p>It is safe to call into its methods from any thread. + * <h3 id="additional-notes">Additional notes</h3> + * + * <p>It is safe to call <code>AutofillManager</code> methods from any thread.   */  @SystemService(Context.AUTOFILL_MANAGER_SERVICE)  @RequiresFeature(PackageManager.FEATURE_AUTOFILL) @@ -2138,7 +2145,11 @@ public final class AutofillManager {          pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId);          pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked());          pw.print(pfx); pw.print("context: "); pw.println(mContext); -        pw.print(pfx); pw.print("client: "); pw.println(getClient()); +        final AutofillClient client = getClient(); +        if (client != null) { +            pw.print(pfx); pw.print("client: "); pw.print(client); +            pw.print(" ("); pw.print(client.autofillClientGetActivityToken()); pw.println(')'); +        }          pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);          pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);          pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null); @@ -2157,8 +2168,24 @@ public final class AutofillManager {          pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds);          pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);          pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish); -        pw.print(pfx); pw.print("compat mode enabled: "); pw.println( -                isCompatibilityModeEnabledLocked()); +        pw.print(pfx); pw.print("compat mode enabled: "); +        synchronized (mLock) { +            if (mCompatibilityBridge != null) { +                final String pfx2 = pfx + "  "; +                pw.println("true"); +                pw.print(pfx2); pw.print("windowId: "); +                pw.println(mCompatibilityBridge.mFocusedWindowId); +                pw.print(pfx2); pw.print("nodeId: "); +                pw.println(mCompatibilityBridge.mFocusedNodeId); +                pw.print(pfx2); pw.print("virtualId: "); +                pw.println(AccessibilityNodeInfo +                        .getVirtualDescendantId(mCompatibilityBridge.mFocusedNodeId)); +                pw.print(pfx2); pw.print("focusedBounds: "); +                pw.println(mCompatibilityBridge.mFocusedBounds); +            } else { +                pw.println("false"); +            } +        }          pw.print(pfx); pw.print("debug: "); pw.print(sDebug);          pw.print(" verbose: "); pw.println(sVerbose);      } @@ -2292,7 +2319,15 @@ public final class AutofillManager {          @Override          public AccessibilityEvent onAccessibilityEvent(AccessibilityEvent event,                  boolean accessibilityEnabled, int relevantEventTypes) { -            switch (event.getEventType()) { +            final int type = event.getEventType(); +            if (sVerbose) { +                // NOTE: this is waaay spammy, but that's life. +                Log.v(TAG, "onAccessibilityEvent(" + AccessibilityEvent.eventTypeToString(type) +                        + "): virtualId=" +                        + AccessibilityNodeInfo.getVirtualDescendantId(event.getSourceNodeId()) +                        + ", client=" + getClient()); +            } +            switch (type) {                  case AccessibilityEvent.TYPE_VIEW_FOCUSED: {                      synchronized (mLock) {                          if (mFocusedWindowId == event.getWindowId() diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java index 0c34e3c16ac6..4d3bbe475920 100644 --- a/core/java/android/webkit/WebBackForwardList.java +++ b/core/java/android/webkit/WebBackForwardList.java @@ -57,7 +57,8 @@ public abstract class WebBackForwardList implements Cloneable, Serializable {      /**       * Clone the entire object to be used in the UI thread by clients of       * WebView. This creates a copy that should never be modified by any of the -     * webkit package classes. +     * webkit package classes. On Android 4.4 and later there is no need to use +     * this, as the object is already a read-only copy of the internal state.       */      protected abstract WebBackForwardList clone();  } diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java index 74db039e015d..b9e704285f84 100644 --- a/core/java/android/webkit/WebHistoryItem.java +++ b/core/java/android/webkit/WebHistoryItem.java @@ -23,7 +23,7 @@ import android.graphics.Bitmap;  /**   * A convenience class for accessing fields in an entry in the back/forward list   * of a WebView. Each WebHistoryItem is a snapshot of the requested history - * item. Each history item may be updated during the load of a page. + * item.   * @see WebBackForwardList   */  public abstract class WebHistoryItem implements Cloneable { @@ -44,8 +44,6 @@ public abstract class WebHistoryItem implements Cloneable {       * history item. See getTargetUrl() for the url that is the actual target of       * this history item.       * @return The base url of this history item. -     * Note: The VM ensures 32-bit atomic read/write operations so we don't have -     * to synchronize this method.       */      public abstract String getUrl(); @@ -60,22 +58,20 @@ public abstract class WebHistoryItem implements Cloneable {      /**       * Return the document title of this history item.       * @return The document title of this history item. -     * Note: The VM ensures 32-bit atomic read/write operations so we don't have -     * to synchronize this method.       */      public abstract String getTitle();      /**       * Return the favicon of this history item or {@code null} if no favicon was found.       * @return A Bitmap containing the favicon for this history item or {@code null}. -     * Note: The VM ensures 32-bit atomic read/write operations so we don't have -     * to synchronize this method.       */      @Nullable      public abstract Bitmap getFavicon();      /** -     * Clone the history item for use by clients of WebView. +     * Clone the history item for use by clients of WebView. On Android 4.4 and later +     * there is no need to use this, as the object is already a read-only copy of the +     * internal state.       */      protected abstract WebHistoryItem clone();  } diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 66e079e26f1f..c30edd30361f 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -991,7 +991,9 @@ public abstract class WebSettings {       * {@link PluginState#OFF}.       *       * @param state a PluginState value -     * @deprecated Plugins will not be supported in future, and should not be used. +     * @deprecated Plugins are not supported in API level +     *             {@link android.os.Build.VERSION_CODES#KITKAT} or later; +     *             enabling plugins is a no-op.       */      @Deprecated      public abstract void setPluginState(PluginState state); @@ -1187,7 +1189,9 @@ public abstract class WebSettings {       *       * @return the plugin state as a {@link PluginState} value       * @see #setPluginState -     * @deprecated Plugins will not be supported in future, and should not be used. +     * @deprecated Plugins are not supported in API level +     *             {@link android.os.Build.VERSION_CODES#KITKAT} or later; +     *             enabling plugins is a no-op.       */      @Deprecated      public abstract PluginState getPluginState(); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 5c5e9de77916..8f03b693e587 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -42,7 +42,6 @@ import android.os.Message;  import android.os.RemoteException;  import android.os.StrictMode;  import android.print.PrintDocumentAdapter; -import android.security.KeyChain;  import android.util.AttributeSet;  import android.util.Log;  import android.util.SparseArray; @@ -1432,9 +1431,8 @@ public class WebView extends AbsoluteLayout      /**       * Clears the client certificate preferences stored in response       * to proceeding/cancelling client cert requests. Note that WebView -     * automatically clears these preferences when it receives a -     * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The preferences are -     * shared by all the WebViews that are created by the embedder application. +     * automatically clears these preferences when the system keychain is updated. +     * The preferences are shared by all the WebViews that are created by the embedder application.       *       * @param onCleared  A runnable to be invoked when client certs are cleared.       *                   The runnable will be called in UI thread. diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index f686b6645655..bdd7a0900213 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -31,18 +31,25 @@ import java.lang.annotation.RetentionPolicy;  public class WebViewClient {      /** -     * Give the host application a chance to take over the control when a new -     * url is about to be loaded in the current WebView. If WebViewClient is not -     * provided, by default WebView will ask Activity Manager to choose the -     * proper handler for the url. If WebViewClient is provided, return {@code true} -     * means the host application handles the url, while return {@code false} means the -     * current WebView handles the url. -     * This method is not called for requests using the POST "method". +     * Give the host application a chance to take control when a URL is about to be loaded in the +     * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity +     * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning +     * {@code true} causes the current WebView to abort loading the URL, while returning +     * {@code false} causes the WebView to continue loading the URL as usual. +     * +     * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the same +     * URL and then return {@code true}. This unnecessarily cancels the current load and starts a +     * new load with the same URL. The correct way to continue loading a given URL is to simply +     * return {@code false}, without calling {@link WebView#loadUrl(String)}. +     * +     * <p class="note"><b>Note:</b> This method is not called for POST requests. +     * +     * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S) +     * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.       *       * @param view The WebView that is initiating the callback. -     * @param url The url to be loaded. -     * @return {@code true} if the host application wants to leave the current WebView -     *         and handle the url itself, otherwise return {@code false}. +     * @param url The URL to be loaded. +     * @return {@code true} to cancel the current load, otherwise return {@code false}.       * @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)       *             shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.       */ @@ -52,26 +59,25 @@ public class WebViewClient {      }      /** -     * Give the host application a chance to take over the control when a new -     * url is about to be loaded in the current WebView. If WebViewClient is not -     * provided, by default WebView will ask Activity Manager to choose the -     * proper handler for the url. If WebViewClient is provided, return {@code true} -     * means the host application handles the url, while return {@code false} means the -     * current WebView handles the url. -     * -     * <p>Notes: -     * <ul> -     * <li>This method is not called for requests using the POST "method".</li> -     * <li>This method is also called for subframes with non-http schemes, thus it is -     * strongly disadvised to unconditionally call {@link WebView#loadUrl(String)} -     * with the request's url from inside the method and then return {@code true}, -     * as this will make WebView to attempt loading a non-http url, and thus fail.</li> -     * </ul> +     * Give the host application a chance to take control when a URL is about to be loaded in the +     * current WebView. If a WebViewClient is not provided, by default WebView will ask Activity +     * Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning +     * {@code true} causes the current WebView to abort loading the URL, while returning +     * {@code false} causes the WebView to continue loading the URL as usual. +     * +     * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the request's +     * URL and then return {@code true}. This unnecessarily cancels the current load and starts a +     * new load with the same URL. The correct way to continue loading a given URL is to simply +     * return {@code false}, without calling {@link WebView#loadUrl(String)}. +     * +     * <p class="note"><b>Note:</b> This method is not called for POST requests. +     * +     * <p class="note"><b>Note:</b> This method may be called for subframes and with non-HTTP(S) +     * schemes; calling {@link WebView#loadUrl(String)} with such a URL will fail.       *       * @param view The WebView that is initiating the callback.       * @param request Object containing the details of the request. -     * @return {@code true} if the host application wants to leave the current WebView -     *         and handle the url itself, otherwise return {@code false}. +     * @return {@code true} to cancel the current load, otherwise return {@code false}.       */      public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {          return shouldOverrideUrlLoading(view, request.getUrl().toString()); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 3956215b6f83..66ce0eeafc96 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -812,7 +812,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te           * @param firstVisibleItem the index of the first visible cell (ignore if           *        visibleItemCount == 0)           * @param visibleItemCount the number of visible cells -         * @param totalItemCount the number of items in the list adaptor +         * @param totalItemCount the number of items in the list adapter           */          public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,                  int totalItemCount); diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 398d08791b5c..4728124c17c5 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -16,14 +16,21 @@  package com.android.internal.app; +import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; + +import android.annotation.Nullable; +import android.annotation.StringRes;  import android.app.Activity;  import android.app.ActivityManager;  import android.app.ActivityThread;  import android.app.AppGlobals;  import android.app.admin.DevicePolicyManager;  import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo;  import android.content.pm.IPackageManager;  import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo;  import android.content.pm.UserInfo;  import android.os.Bundle;  import android.os.RemoteException; @@ -31,12 +38,11 @@ import android.os.UserHandle;  import android.os.UserManager;  import android.util.Slog;  import android.widget.Toast; -  import com.android.internal.annotations.VisibleForTesting; - +import java.util.Arrays; +import java.util.HashSet;  import java.util.List; - -import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; +import java.util.Set;  /**   * This is used in conjunction with @@ -44,7 +50,6 @@ import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;   * be passed in and out of a managed profile.   */  public class IntentForwarderActivity extends Activity  { -      public static String TAG = "IntentForwarderActivity";      public static String FORWARD_INTENT_TO_PARENT @@ -53,6 +58,9 @@ public class IntentForwarderActivity extends Activity  {      public static String FORWARD_INTENT_TO_MANAGED_PROFILE              = "com.android.internal.app.ForwardIntentToManagedProfile"; +    private static final Set<String> ALLOWED_TEXT_MESSAGE_SCHEME +            = new HashSet<>(Arrays.asList("sms", "smsto", "mms", "mmsto")); +      private Injector mInjector;      @Override @@ -93,19 +101,8 @@ public class IntentForwarderActivity extends Activity  {                  newIntent.prepareToLeaveUser(callingUserId);              } -            final android.content.pm.ResolveInfo ri = -                    mInjector.getPackageManager().resolveActivityAsUser( -                            newIntent, -                            MATCH_DEFAULT_ONLY, -                            targetUserId); - -            // Don't show the disclosure if next activity is ResolverActivity or ChooserActivity -            // as those will already have shown work / personal as neccesary etc. -            final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || -                    !"android".equals(ri.activityInfo.packageName) || -                    !(ResolverActivity.class.getName().equals(ri.activityInfo.name) -                            || ChooserActivity.class.getName().equals(ri.activityInfo.name)); - +            final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, +                    targetUserId);              try {                  startActivityAsCaller(newIntent, null, false, targetUserId);              } catch (RuntimeException e) { @@ -124,8 +121,8 @@ public class IntentForwarderActivity extends Activity  {                          + ActivityThread.currentProcessName(), e);              } -            if (shouldShowDisclosure) { -                Toast.makeText(this, getString(userMessageId), Toast.LENGTH_LONG).show(); +            if (shouldShowDisclosure(ri, intentReceived)) { +                mInjector.showToast(userMessageId, Toast.LENGTH_LONG);              }          } else {              Slog.wtf(TAG, "the intent: " + intentReceived + " cannot be forwarded from user " @@ -134,6 +131,35 @@ public class IntentForwarderActivity extends Activity  {          finish();      } +    private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) { +        if (ri == null || ri.activityInfo == null) { +            return true; +        } +        if (ri.activityInfo.applicationInfo.isSystemApp() +                && (isDialerIntent(intent) || isTextMessageIntent(intent))) { +            return false; +        } +        return !isTargetResolverOrChooserActivity(ri.activityInfo); +    } + +    private boolean isTextMessageIntent(Intent intent) { +        return Intent.ACTION_SENDTO.equals(intent.getAction()) && intent.getData() != null +            && ALLOWED_TEXT_MESSAGE_SCHEME.contains(intent.getData().getScheme()); +    } + +    private boolean isDialerIntent(Intent intent) { +        return Intent.ACTION_DIAL.equals(intent.getAction()) +            || Intent.ACTION_CALL.equals(intent.getAction()); +    } + +    private boolean isTargetResolverOrChooserActivity(ActivityInfo activityInfo) { +        if (!"android".equals(activityInfo.packageName)) { +            return false; +        } +        return ResolverActivity.class.getName().equals(activityInfo.name) +            || ChooserActivity.class.getName().equals(activityInfo.name); +    } +      /**       * Check whether the intent can be forwarded to target user. Return the intent used for       * forwarding if it can be forwarded, {@code null} otherwise. @@ -241,6 +267,16 @@ public class IntentForwarderActivity extends Activity  {          public PackageManager getPackageManager() {              return IntentForwarderActivity.this.getPackageManager();          } + +        @Override +        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { +            return getPackageManager().resolveActivityAsUser(intent, flags, userId); +        } + +        @Override +        public void showToast(int messageId, int duration) { +            Toast.makeText(IntentForwarderActivity.this, getString(messageId), duration).show(); +        }      }      public interface Injector { @@ -249,5 +285,9 @@ public class IntentForwarderActivity extends Activity  {          UserManager getUserManager();          PackageManager getPackageManager(); + +        ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId); + +        void showToast(@StringRes int messageId, int duration);      }  } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 94c3933c55f0..e6dc352e63af 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4031,7 +4031,9 @@ public class BatteryStatsImpl extends BatteryStats {          try {              IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub.asInterface(                      ServiceManager.getService("batteryproperties")); -            registrar.scheduleUpdate(); +            if (registrar != null) { +                registrar.scheduleUpdate(); +            }          } catch (RemoteException e) {              // Ignore.          } diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java index 64b1f241464b..0c8613b460f6 100644 --- a/core/java/com/android/internal/widget/MessagingLinearLayout.java +++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java @@ -111,14 +111,16 @@ public class MessagingLinearLayout extends ViewGroup {              final int childHeight = child.getMeasuredHeight();              int newHeight = Math.max(totalHeight, totalHeight + childHeight + lp.topMargin +                      lp.bottomMargin + spacing); -            first = false;              int measureType = MessagingChild.MEASURED_NORMAL;              if (messagingChild != null) {                  measureType = messagingChild.getMeasuredType();                  linesRemaining -= messagingChild.getConsumedLines();              } -            boolean isShortened = measureType == MessagingChild.MEASURED_SHORTENED; -            boolean isTooSmall = measureType == MessagingChild.MEASURED_TOO_SMALL; + +            // We never measure the first item as too small, we want to at least show something. +            boolean isTooSmall = measureType == MessagingChild.MEASURED_TOO_SMALL && !first; +            boolean isShortened = measureType == MessagingChild.MEASURED_SHORTENED +                    || measureType == MessagingChild.MEASURED_TOO_SMALL && first;              if (newHeight <= targetHeight && !isTooSmall) {                  totalHeight = newHeight;                  measuredWidth = Math.max(measuredWidth, @@ -131,6 +133,7 @@ public class MessagingLinearLayout extends ViewGroup {              } else {                  break;              } +            first = false;          }          setMeasuredDimension( diff --git a/core/res/res/values-mcc214-mnc01/config.xml b/core/res/res/values-mcc214-mnc01/config.xml index 24150a782d22..41e24d779362 100644 --- a/core/res/res/values-mcc214-mnc01/config.xml +++ b/core/res/res/values-mcc214-mnc01/config.xml @@ -40,4 +40,7 @@        <item>INTERNET,airtelnet.es,,,vodafone,vodafone,,,,,214,01,1,DUN</item>      </string-array> +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">false</bool> +  </resources> diff --git a/core/res/res/values-mcc222-mnc10/config.xml b/core/res/res/values-mcc222-mnc10/config.xml index c819de2ba43c..0085a1b7e190 100644 --- a/core/res/res/values-mcc222-mnc10/config.xml +++ b/core/res/res/values-mcc222-mnc10/config.xml @@ -28,4 +28,8 @@      <string-array translatable="false" name="config_tether_apndata">        <item>Tethering Internet,web.omnitel.it,,,,,,,,,222,10,,DUN</item>      </string-array> + +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">false</bool> +  </resources> diff --git a/core/res/res/values-mcc234-mnc15/config.xml b/core/res/res/values-mcc234-mnc15/config.xml new file mode 100644 index 000000000000..84e779d240d1 --- /dev/null +++ b/core/res/res/values-mcc234-mnc15/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2018, 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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">false</bool> + +</resources> diff --git a/core/res/res/values-mcc234-mnc91/config.xml b/core/res/res/values-mcc234-mnc91/config.xml new file mode 100644 index 000000000000..84e779d240d1 --- /dev/null +++ b/core/res/res/values-mcc234-mnc91/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2018, 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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">false</bool> + +</resources> diff --git a/core/res/res/values-mcc262-mnc02/config.xml b/core/res/res/values-mcc262-mnc02/config.xml new file mode 100644 index 000000000000..84e779d240d1 --- /dev/null +++ b/core/res/res/values-mcc262-mnc02/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2018, 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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">false</bool> + +</resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 969b6021689c..8f1c9320c762 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -670,6 +670,10 @@      <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements -->      <bool translatable="false" name="config_wifi_framework_enable_sar_tx_power_limit">false</bool> +    <!-- Boolean indicating whether framework should use detection of softAP mode to set the tx +         power limit for meeting SAR requirements --> +    <bool translatable="false" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit">false</bool> +      <!-- Boolean indicating whether framework needs to use body proximity to set the tx power limit           for meeting SAR requirements -->      <bool translatable="false" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit">false</bool> @@ -2357,6 +2361,9 @@      <!-- Whether safe headphone volume is enabled or not (country specific). -->      <bool name="config_safe_media_volume_enabled">true</bool> +    <!-- Whether safe headphone volume warning dialog is disabled on Vol+ (operator specific). --> +    <bool name="config_safe_media_disable_on_volume_up">true</bool> +      <!-- Set to true if the wifi display supports compositing content stored           in gralloc protected buffers.  For this to be true, there must exist           a protected hardware path for surface flinger to composite and send @@ -2979,6 +2986,10 @@           -->      <bool name="config_fillMainBuiltInDisplayCutout">false</bool> +    <!-- If true, and there is a cutout on the main built in display, the cutout will be masked +         by shrinking the display such that it does not overlap the cutout area. --> +    <bool name="config_maskMainBuiltInDisplayCutout">false</bool> +      <!-- Ultrasound support for Mic/speaker path -->      <!-- Whether the default microphone audio source supports near-ultrasound frequencies           (range of 18 - 21 kHz). --> @@ -3502,4 +3513,11 @@      <!-- Whether or not we should show the option to show battery percentage -->      <bool name="config_battery_percentage_setting_available">true</bool> + +    <!-- Model of potentially misprovisioned devices. If none is specified in an overlay, an +         empty string is passed in. --> +    <string name="config_misprovisionedDeviceModel" translatable="false"></string> + +    <!-- Brand value for attestation of misprovisioned device. --> +    <string name="config_misprovisionedBrandValue" translatable="false"></string>  </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 471170bbe93b..73cb59e84644 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -61,6 +61,15 @@      <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->      <dimen name="status_bar_edge_ignore">5dp</dimen> +    <!-- Default radius of the software rounded corners. --> +    <dimen name="rounded_corner_radius">0dp</dimen> +    <!-- Radius of the software rounded corners at the top of the display in its natural +        orientation. If zero, the value of rounded_corner_radius is used. --> +    <dimen name="rounded_corner_radius_top">0dp</dimen> +    <!-- Radius of the software rounded corners at the bottom of the display in its natural +        orientation. If zero, the value of rounded_corner_radius is used. --> +    <dimen name="rounded_corner_radius_bottom">0dp</dimen> +      <!-- Width of the window of the divider bar used to resize docked stacks. -->      <dimen name="docked_stack_divider_thickness">48dp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9520d6d05960..4fd94a217207 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -310,6 +310,7 @@    <java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />    <java-symbol type="bool" name="config_useDevInputEventForAudioJack" />    <java-symbol type="bool" name="config_safe_media_volume_enabled" /> +  <java-symbol type="bool" name="config_safe_media_disable_on_volume_up" />    <java-symbol type="bool" name="config_camera_sound_forced" />    <java-symbol type="bool" name="config_dontPreferApn" />    <java-symbol type="bool" name="config_restartRadioAfterProvisioning" /> @@ -338,6 +339,7 @@    <java-symbol type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" />    <java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />    <java-symbol type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" /> +  <java-symbol type="bool" name="config_wifi_framework_enable_soft_ap_sar_tx_power_limit" />    <java-symbol type="bool" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit" />    <java-symbol type="string" name="config_wifi_sar_sensor_type" />    <java-symbol type="integer" name="config_wifi_framework_sar_free_space_event_id" /> @@ -3407,6 +3409,11 @@    <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />    <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> +  <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" /> +    <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />    <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> + +  <java-symbol type="string" name="config_misprovisionedDeviceModel" /> +  <java-symbol type="string" name="config_misprovisionedBrandValue" />  </resources> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 483381660655..090f9afb551e 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -306,6 +306,7 @@ please see themes_device_defaults.xml.          <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.QuickContactBadgeSmall.WindowLarge</item>          <item name="listPopupWindowStyle">@style/Widget.ListPopupWindow</item>          <item name="popupMenuStyle">@style/Widget.PopupMenu</item> +        <item name="popupTheme">@null</item>          <item name="activityChooserViewStyle">@style/Widget.ActivityChooserView</item>          <item name="fragmentBreadCrumbsStyle">@style/Widget.FragmentBreadCrumbs</item>          <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item> diff --git a/core/res/res/values/themes_holo.xml b/core/res/res/values/themes_holo.xml index cb5b93dd7df4..33832d4eb689 100644 --- a/core/res/res/values/themes_holo.xml +++ b/core/res/res/values/themes_holo.xml @@ -296,6 +296,7 @@ please see themes_device_defaults.xml.          <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>          <item name="listPopupWindowStyle">@style/Widget.Holo.ListPopupWindow</item>          <item name="popupMenuStyle">@style/Widget.Holo.PopupMenu</item> +        <item name="popupTheme">@null</item>          <item name="stackViewStyle">@style/Widget.Holo.StackView</item>          <item name="activityChooserViewStyle">@style/Widget.Holo.ActivityChooserView</item>          <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.FragmentBreadCrumbs</item> @@ -658,9 +659,11 @@ please see themes_device_defaults.xml.          <item name="quickContactBadgeStyleSmallWindowLarge">@style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>          <item name="listPopupWindowStyle">@style/Widget.Holo.Light.ListPopupWindow</item>          <item name="popupMenuStyle">@style/Widget.Holo.Light.PopupMenu</item> +        <item name="popupTheme">@null</item>          <item name="stackViewStyle">@style/Widget.Holo.StackView</item>          <item name="activityChooserViewStyle">@style/Widget.Holo.Light.ActivityChooserView</item>          <item name="fragmentBreadCrumbsStyle">@style/Widget.Holo.Light.FragmentBreadCrumbs</item> +        <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>          <!-- Preference styles -->          <item name="preferenceScreenStyle">@style/Preference.Holo.PreferenceScreen</item> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 43af1a3eb804..583b2cd91730 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -99,6 +99,7 @@ public class SettingsBackupTest {      private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =              newHashSet(                      Settings.Global.ACTIVITY_MANAGER_CONSTANTS, +                    Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED,                      Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED,                      Settings.Global.ADB_ENABLED,                      Settings.Global.ADD_USERS_WHEN_LOCKED, diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index 6ee74cb9a742..fe45fe7d3aaf 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -19,6 +19,7 @@ package android.view;  import static android.view.DisplayCutout.NO_CUTOUT;  import static android.view.DisplayCutout.fromSpec; +import static org.hamcrest.Matchers.equalTo;  import static org.hamcrest.Matchers.not;  import static org.hamcrest.Matchers.sameInstance;  import static org.junit.Assert.assertEquals; @@ -220,6 +221,19 @@ public class DisplayCutoutTest {      }      @Test +    public void fromSpec_setsSafeInsets_top() { +        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f); +        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0))); +    } + +    @Test +    public void fromSpec_setsSafeInsets_top_and_bottom() { +        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z" +                + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f); +        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10))); +    } + +    @Test      public void parcel_unparcel_nocutout() {          Parcel p = Parcel.obtain(); diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java index b18fa747557d..c165b6be525e 100644 --- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java @@ -16,46 +16,50 @@  package com.android.internal.app; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +  import android.annotation.Nullable;  import android.content.ComponentName;  import android.content.Context;  import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo;  import android.content.pm.IPackageManager;  import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo;  import android.content.pm.UserInfo; +import android.net.Uri;  import android.os.Bundle; +import android.os.RemoteException;  import android.os.UserHandle;  import android.os.UserManager;  import android.support.test.InstrumentationRegistry;  import android.support.test.rule.ActivityTestRule;  import android.support.test.runner.AndroidJUnit4; -import android.util.Log; - +import java.util.ArrayList; +import java.util.List;  import org.junit.Before;  import org.junit.Rule;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.ArgumentCaptor;  import org.mockito.Mock; -import org.mockito.Mockito;  import org.mockito.MockitoAnnotations; -import java.util.ArrayList; -import java.util.List; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -  @RunWith(AndroidJUnit4.class)  public class IntentForwarderActivityTest { +      private static final ComponentName FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME =              new ComponentName(                      "android", @@ -77,22 +81,26 @@ public class IntentForwarderActivityTest {      private static IntentForwarderActivity.Injector sInjector;      private static ComponentName sComponentName; +    private static String sActivityName; +    private static String sPackageName;      @Mock private IPackageManager mIPm;      @Mock private PackageManager mPm;      @Mock private UserManager mUserManager; +    @Mock private ApplicationInfo mApplicationInfo;      @Rule      public ActivityTestRule<IntentForwarderWrapperActivity> mActivityRule =              new ActivityTestRule<>(IntentForwarderWrapperActivity.class, true, false);      private Context mContext; +    public static final String PHONE_NUMBER = "123-456-789";      @Before      public void setup() {          MockitoAnnotations.initMocks(this);          mContext = InstrumentationRegistry.getTargetContext(); -        sInjector = new TestInjector(); +        sInjector = spy(new TestInjector());      }      @Test @@ -252,6 +260,149 @@ public class IntentForwarderActivityTest {          assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn);      } +    @Test +    public void shouldSkipDisclosure_notWhitelisted() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SEND) +            .setType(TYPE_PLAIN_TEXT); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_withResolverActivity() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        sActivityName = ResolverActivity.class.getName(); +        sPackageName = "android"; +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SEND) +            .setType(TYPE_PLAIN_TEXT); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_callIntent_call() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_CALL); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_callIntent_dial() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_DIAL); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_callIntent_notCallOrDial() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_ALARM_CHANGED); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_textMessageIntent_sms() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SENDTO) +            .setData(Uri.fromParts("sms", PHONE_NUMBER, null)); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_textMessageIntent_smsto() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SENDTO) +            .setData(Uri.fromParts("smsto", PHONE_NUMBER, null)); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_textMessageIntent_mms() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SENDTO) +            .setData(Uri.fromParts("mms", PHONE_NUMBER, null)); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_textMessageIntent_mmsto() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SENDTO) +            .setData(Uri.fromParts("mmsto", PHONE_NUMBER, null)); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector, never()).showToast(anyInt(), anyInt()); +    } + +    @Test +    public void shouldSkipDisclosure_textMessageIntent_invalidUri() throws RemoteException { +        setupShouldSkipDisclosureTest(); +        Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class) +            .setAction(Intent.ACTION_SENDTO) +            .setData(Uri.fromParts("invalid", PHONE_NUMBER, null)); + +        mActivityRule.launchActivity(intent); + +        verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt()); +        verify(sInjector).showToast(anyInt(), anyInt()); +    } + +    private void setupShouldSkipDisclosureTest() throws RemoteException { +        sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; +        sActivityName = "MyTestActivity"; +        sPackageName = "test.package.name"; +        when(mApplicationInfo.isSystemApp()).thenReturn(true); +        // Managed profile exists. +        List<UserInfo> profiles = new ArrayList<>(); +        profiles.add(CURRENT_USER_INFO); +        profiles.add(MANAGED_PROFILE_INFO); +        when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); +        // Intent can be forwarded. +        when(mIPm.canForwardTo( +            any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); +    }      public static class IntentForwarderWrapperActivity extends IntentForwarderActivity {          private Intent mStartActivityIntent; @@ -276,7 +427,7 @@ public class IntentForwarderActivityTest {          }      } -    class TestInjector implements IntentForwarderActivity.Injector { +    public class TestInjector implements IntentForwarderActivity.Injector {          @Override          public IPackageManager getIPackageManager() { @@ -292,5 +443,21 @@ public class IntentForwarderActivityTest {          public PackageManager getPackageManager() {              return mPm;          } + +        @Override +        public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { +            ActivityInfo activityInfo = new ActivityInfo(); +            activityInfo.packageName = sPackageName; +            activityInfo.name = sActivityName; +            activityInfo.applicationInfo = mApplicationInfo; + +            ResolveInfo resolveInfo = new ResolveInfo(); +            resolveInfo.activityInfo = activityInfo; + +            return resolveInfo; +        } + +        @Override +        public void showToast(int messageId, int duration) {}      }  }
\ No newline at end of file diff --git a/data/etc/platform.xml b/data/etc/platform.xml index b3f05dc9fc98..6f52fbd1b4f5 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -182,11 +182,11 @@           code to link against. -->      <library name="android.test.base" -            file="/system/framework/android.test.base.jar" /> +            file="/system/framework/android.test.base.impl.jar" />      <library name="android.test.mock" -            file="/system/framework/android.test.mock.jar" /> +            file="/system/framework/android.test.mock.impl.jar" />      <library name="android.test.runner" -            file="/system/framework/android.test.runner.jar" /> +            file="/system/framework/android.test.runner.impl.jar" />      <!-- These are the standard packages that are white-listed to always have internet           access while in power save mode, even if they aren't in the foreground. --> diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 2503381a501f..ef58c8f2bd16 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1600,9 +1600,9 @@ public class Canvas extends BaseCanvas {       * Draw the specified circle using the specified paint. If radius is <= 0, then nothing will be       * drawn. The circle will be filled or framed based on the Style in the paint.       * -     * @param cx The x-coordinate of the center of the cirle to be drawn -     * @param cy The y-coordinate of the center of the cirle to be drawn -     * @param radius The radius of the cirle to be drawn +     * @param cx The x-coordinate of the center of the circle to be drawn +     * @param cy The y-coordinate of the center of the circle to be drawn +     * @param radius The radius of the circle to be drawn       * @param paint The paint used to draw the circle       */      public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index 419eb24e1cc1..953cef7d30ff 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -301,6 +301,9 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {                  KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(                          mRng, (mKeySizeBits + 7) / 8);          int flags = 0; +        if (spec.isStrongBoxBacked()) { +            flags |= KeyStore.FLAG_STRONGBOX; +        }          String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + spec.getKeystoreAlias();          KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();          boolean success = false; @@ -314,8 +317,12 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {                      flags,                      resultingKeyCharacteristics);              if (errorCode != KeyStore.NO_ERROR) { -                throw new ProviderException( -                        "Keystore operation failed", KeyStore.getKeyStoreException(errorCode)); +                if (errorCode == KeyStore.HARDWARE_TYPE_UNAVAILABLE) { +                    throw new StrongBoxUnavailableException("Failed to generate key"); +                } else { +                    throw new ProviderException( +                            "Keystore operation failed", KeyStore.getKeyStoreException(errorCode)); +                }              }              @KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;              try { diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java index 1be8309bcf5a..f7993eff6b08 100644 --- a/keystore/java/android/security/keystore/AttestationUtils.java +++ b/keystore/java/android/security/keystore/AttestationUtils.java @@ -22,9 +22,9 @@ import android.annotation.RequiresPermission;  import android.annotation.SystemApi;  import android.annotation.TestApi;  import android.content.Context; +import android.content.res.Resources;  import android.os.Build;  import android.security.KeyStore; -import android.security.KeyStoreException;  import android.security.keymaster.KeymasterArguments;  import android.security.keymaster.KeymasterCertificateChain;  import android.security.keymaster.KeymasterDefs; @@ -117,6 +117,40 @@ public abstract class AttestationUtils {      @NonNull public static KeymasterArguments prepareAttestationArguments(Context context,              @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws              DeviceIdAttestationException { +        return prepareAttestationArguments(context, idTypes,attestationChallenge, Build.BRAND); +    } + +    /** +     * Prepares Keymaster Arguments with attestation data for misprovisioned Pixel 2 device. +     * See http://go/keyAttestationFailure and http://b/69471841 for more info. +     * @hide should only be used by KeyChain. +     */ +    @NonNull public static KeymasterArguments prepareAttestationArgumentsIfMisprovisioned( +            Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws +            DeviceIdAttestationException { +        if (!isPotentiallyMisprovisionedDevice(context)) { +            return null; +        } +        Resources resources = context.getResources(); +        String misprovisionedBrand = resources.getString( +                com.android.internal.R.string.config_misprovisionedBrandValue); +        return prepareAttestationArguments( +                    context, idTypes, attestationChallenge, misprovisionedBrand); +    } + +    @NonNull private static boolean isPotentiallyMisprovisionedDevice(Context context) { +        Resources resources = context.getResources(); +        String misprovisionedModel = resources.getString( +                com.android.internal.R.string.config_misprovisionedDeviceModel); +        String misprovisionedBrand = resources.getString( +                com.android.internal.R.string.config_misprovisionedBrandValue); + +        return (Build.MODEL.equals(misprovisionedModel)); +    } + +    @NonNull private static KeymasterArguments prepareAttestationArguments(Context context, +            @NonNull int[] idTypes, @NonNull byte[] attestationChallenge, String brand) throws +            DeviceIdAttestationException {          // Check method arguments, retrieve requested device IDs and prepare attestation arguments.          if (attestationChallenge == null) {              throw new NullPointerException("Missing attestation challenge"); @@ -169,7 +203,7 @@ public abstract class AttestationUtils {              }          }          attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND, -                Build.BRAND.getBytes(StandardCharsets.UTF_8)); +                brand.getBytes(StandardCharsets.UTF_8));          attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,                  Build.DEVICE.getBytes(StandardCharsets.UTF_8));          attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT, diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java index 3643ca4a02f7..8a02a82194df 100644 --- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java +++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java @@ -18,6 +18,7 @@ package com.android.internal.location.gnssmetrics;  import android.os.SystemClock;  import android.os.connectivity.GpsBatteryStats; +import android.os.SystemProperties;  import android.text.format.DateUtils;  import android.util.Base64; @@ -175,6 +176,7 @@ public class GnssMetrics {            = topFourAverageCn0Statistics.getStandardDeviation();      }      msg.powerMetrics = mGnssPowerMetrics.buildProto(); +    msg.hardwareRevision = SystemProperties.get("ro.boot.revision", "");      String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT);      reset();      return s; @@ -239,6 +241,7 @@ public class GnssMetrics {        s.append("  Energy consumed while on battery (mAh): ").append(            stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append("\n");      } +    s.append("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")).append("\n");      return s.toString();    } diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 76fc9e350ecc..d45acdfa627e 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -405,7 +405,7 @@ import java.util.Map;   <p>   The codec in turn will return a read-only output buffer via the {@link   Callback#onOutputBufferAvailable onOutputBufferAvailable} callback in asynchronous mode, or in - response to a {@link #dequeueOutputBuffer dequeuOutputBuffer} call in synchronous mode. After the + response to a {@link #dequeueOutputBuffer dequeueOutputBuffer} call in synchronous mode. After the   output buffer has been processed, call one of the {@link #releaseOutputBuffer   releaseOutputBuffer} methods to return the buffer to the codec.   <p> diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp new file mode 100644 index 000000000000..4791517d9273 --- /dev/null +++ b/packages/SettingsLib/Android.bp @@ -0,0 +1,25 @@ +android_library { + +    name: "SettingsLib", + +    libs: [ +        "androidx.annotation_annotation", +        "androidx.legacy_legacy-support-v4", +        "androidx.recyclerview_recyclerview", +        "androidx.preference_preference", +        "androidx.appcompat_appcompat", +        "androidx.lifecycle_lifecycle-runtime", +    ], + +    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES +    // LOCAL_SHARED_JAVA_LIBRARIES := androidx.lifecycle_lifecycle-common + +    resource_dirs: ["res"], + +    srcs: ["src/**/*.java"], + +    min_sdk_version: "21", + +} + +// For the test package. diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk deleted file mode 100644 index 96012c1f2a34..000000000000 --- a/packages/SettingsLib/Android.mk +++ /dev/null @@ -1,34 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_USE_AAPT2 := true - -LOCAL_AAPT2_ONLY := true - -LOCAL_MODULE := SettingsLib - -LOCAL_JAVA_LIBRARIES := \ -    androidx.annotation_annotation - -LOCAL_SHARED_ANDROID_LIBRARIES := \ -    androidx.legacy_legacy-support-v4 \ -    androidx.recyclerview_recyclerview \ -    androidx.preference_preference \ -    androidx.appcompat_appcompat \ -    androidx.lifecycle_lifecycle-runtime - -LOCAL_SHARED_JAVA_LIBRARIES := \ -    androidx.lifecycle_lifecycle-common - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -LOCAL_JAR_EXCLUDE_FILES := none - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_MIN_SDK_VERSION := 21 - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# For the test package. -include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index a3c1fc6ff265..fd80edf839bc 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -62,6 +62,7 @@ import java.io.File;  import java.io.IOException;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference;  import java.text.Collator;  import java.text.Normalizer;  import java.text.Normalizer.Form; @@ -132,7 +133,7 @@ public class ApplicationsState {      boolean mSessionsChanged;      // Temporary for dispatching session callbacks.  Only touched by main thread. -    final ArrayList<Session> mActiveSessions = new ArrayList<Session>(); +    final ArrayList<WeakReference<Session>> mActiveSessions = new ArrayList<>();      final HandlerThread mThread;      final BackgroundHandler mBackgroundHandler; @@ -618,7 +619,7 @@ public class ApplicationsState {              for (int i=0; i<mSessions.size(); i++) {                  Session s = mSessions.get(i);                  if (s.mResumed) { -                    mActiveSessions.add(s); +                    mActiveSessions.add(new WeakReference<>(s));                  }              }          } @@ -830,46 +831,70 @@ public class ApplicationsState {              rebuildActiveSessions();              switch (msg.what) {                  case MSG_REBUILD_COMPLETE: { -                    Session s = (Session)msg.obj; -                    if (mActiveSessions.contains(s)) { -                        s.mCallbacks.onRebuildComplete(s.mLastAppList); +                    Session s = (Session) msg.obj; +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null && session == s) { +                            s.mCallbacks.onRebuildComplete(s.mLastAppList); +                        }                      }                  } break;                  case MSG_PACKAGE_LIST_CHANGED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onPackageListChanged(); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onPackageListChanged(); +                        }                      }                  } break;                  case MSG_PACKAGE_ICON_CHANGED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onPackageIconChanged(); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onPackageIconChanged(); +                        }                      }                  } break;                  case MSG_PACKAGE_SIZE_CHANGED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onPackageSizeChanged( -                                (String)msg.obj); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onPackageSizeChanged( +                                    (String) msg.obj); +                        }                      }                  } break;                  case MSG_ALL_SIZES_COMPUTED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onAllSizesComputed(); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onAllSizesComputed(); +                        }                      }                  } break;                  case MSG_RUNNING_STATE_CHANGED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onRunningStateChanged( -                                msg.arg1 != 0); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onRunningStateChanged( +                                    msg.arg1 != 0); +                        }                      }                  } break;                  case MSG_LAUNCHER_INFO_CHANGED: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onLauncherInfoChanged(); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onLauncherInfoChanged(); +                        }                      }                  } break;                  case MSG_LOAD_ENTRIES_COMPLETE: { -                    for (int i=0; i<mActiveSessions.size(); i++) { -                        mActiveSessions.get(i).mCallbacks.onLoadEntriesCompleted(); +                    for (WeakReference<Session> sessionRef : mActiveSessions) { +                        final Session session = sessionRef.get(); +                        if (session != null) { +                            session.mCallbacks.onLoadEntriesCompleted(); +                        }                      }                  } break;              } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java index 373247162563..1c50953bac12 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java @@ -19,6 +19,8 @@ package com.android.settingslib.bluetooth;  import android.content.Context;  import android.util.Log; +import java.lang.ref.WeakReference; +  /**   * LocalBluetoothManager provides a simplified interface on top of a subset of   * the Bluetooth API. Note that {@link #getInstance} will return null @@ -34,7 +36,7 @@ public class LocalBluetoothManager {      private final Context mContext;      /** If a BT-related activity is in the foreground, this will be it. */ -    private Context mForegroundActivity; +    private WeakReference<Context> mForegroundActivity;      private final LocalBluetoothAdapter mLocalAdapter; @@ -85,17 +87,19 @@ public class LocalBluetoothManager {      }      public Context getForegroundActivity() { -        return mForegroundActivity; +        return mForegroundActivity == null +                ? null +                : mForegroundActivity.get();      }      public boolean isForegroundActivity() { -        return mForegroundActivity != null; +        return mForegroundActivity != null && mForegroundActivity.get() != null;      }      public synchronized void setForegroundActivity(Context context) {          if (context != null) {              Log.d(TAG, "setting foreground activity to non-null context"); -            mForegroundActivity = context; +            mForegroundActivity = new WeakReference<>(context);          } else {              if (mForegroundActivity != null) {                  Log.d(TAG, "setting foreground activity to null"); diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java index 988060eac64d..e5d97c9b4a7b 100644 --- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java +++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java @@ -36,12 +36,12 @@ import android.util.AttributeSet;  import android.util.Log;  import android.util.Xml; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy;  import org.xmlpull.v1.XmlPullParser;  import org.xmlpull.v1.XmlPullParserException;  import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy;  import java.util.ArrayList;  import java.util.Collections;  import java.util.Comparator; @@ -97,15 +97,15 @@ public class DreamBackend {      }      public DreamBackend(Context context) { -        mContext = context; +        mContext = context.getApplicationContext();          mDreamManager = IDreamManager.Stub.asInterface(                  ServiceManager.getService(DreamService.DREAM_SERVICE));          mComparator = new DreamInfoComparator(getDefaultDream()); -        mDreamsEnabledByDefault = context.getResources() +        mDreamsEnabledByDefault = mContext.getResources()                  .getBoolean(com.android.internal.R.bool.config_dreamsEnabledByDefault); -        mDreamsActivatedOnSleepByDefault = context.getResources() +        mDreamsActivatedOnSleepByDefault = mContext.getResources()                  .getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault); -        mDreamsActivatedOnDockByDefault = context.getResources() +        mDreamsActivatedOnDockByDefault = mContext.getResources()                  .getBoolean(com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);      } diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp new file mode 100644 index 000000000000..c9ba26804e89 --- /dev/null +++ b/packages/SystemUI/Android.bp @@ -0,0 +1,101 @@ +// +// Copyright (C) 2018 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. +// + +java_library { +    name: "SystemUI-proto", + +    srcs: ["src/**/*.proto"], + +    proto: { +        type: "nano", +    }, +} + +java_library { +    name: "SystemUI-tags", +    srcs: ["src/com/android/systemui/EventLogTags.logtags"], +} + +android_library { +    name: "SystemUI-core", +    srcs: [ +        "src/**/*.java", +        "src/**/I*.aidl", +    ], +    resource_dirs: [ +        "res-keyguard", +        "res", +    ], +    static_libs: [ +        "SystemUIPluginLib", +        "SystemUISharedLib", +        "SettingsLib", +        "androidx.car_car", +        "androidx.legacy_legacy-support-v4", +        "androidx.recyclerview_recyclerview", +        "androidx.preference_preference", +        "androidx.appcompat_appcompat", +        "androidx.mediarouter_mediarouter", +        "androidx.palette_palette", +        "androidx.legacy_legacy-preference-v14", +        "androidx.leanback_leanback", +        "androidx.slice_slice-core", +        "androidx.slice_slice-view", +        "androidx.slice_slice-builders", +        "androidx.arch.core_core-runtime", +        "androidx.lifecycle_lifecycle-extensions", +        "SystemUI-tags", +        "SystemUI-proto", +    ], +    manifest: "AndroidManifest.xml", + +    libs: [ +        "telephony-common", +        "android.car", +    ], + +    aaptflags: [ +        "--extra-packages", +        "com.android.keyguard", +    ], +} + +android_app { +    name: "SystemUI", +    static_libs: [ +        "SystemUI-core", +    ], + +    platform_apis: true, +    certificate: "platform", +    privileged: true, + +    optimize: { +        proguard_flags_files: ["proguard.flags"], +    }, + +    libs: [ +        "telephony-common", +        "android.car", +    ], + +    dxflags: ["--multi-dex"], +    aaptflags: [ +        "--extra-packages", +        "com.android.keyguard", +    ], + +} diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk deleted file mode 100644 index d9ec0fd0214b..000000000000 --- a/packages/SystemUI/Android.mk +++ /dev/null @@ -1,83 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := SystemUI-proto - -LOCAL_SRC_FILES := $(call all-proto-files-under,src) - -LOCAL_PROTOC_OPTIMIZE_TYPE := nano -LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(CLEAR_VARS) - -LOCAL_MODULE := SystemUI-tags - -LOCAL_SRC_FILES := src/com/android/systemui/EventLogTags.logtags - -include $(BUILD_STATIC_JAVA_LIBRARY) - -# ------------------ - -include $(CLEAR_VARS) - -LOCAL_USE_AAPT2 := true - -LOCAL_MODULE_TAGS := optional - -RELATIVE_FINGERPRINT_PATH := ../../core/java/android/hardware/fingerprint - -LOCAL_SRC_FILES := \ -    $(call all-java-files-under, src) \ -    $(call all-Iaidl-files-under, src) \ -    $(call all-Iaidl-files-under, $(RELATIVE_FINGERPRINT_PATH)) - -LOCAL_STATIC_ANDROID_LIBRARIES := \ -    SystemUIPluginLib \ -    SystemUISharedLib \ -    androidx.car_car \ -    androidx.legacy_legacy-support-v4 \ -    androidx.recyclerview_recyclerview \ -    androidx.preference_preference \ -    androidx.appcompat_appcompat \ -    androidx.mediarouter_mediarouter \ -    androidx.palette_palette \ -    androidx.legacy_legacy-preference-v14 \ -    androidx.leanback_leanback \ -    androidx.slice_slice-core \ -    androidx.slice_slice-view \ -    androidx.slice_slice-builders \ -    androidx.arch.core_core-runtime \ -    androidx.lifecycle_lifecycle-extensions \ - -LOCAL_STATIC_JAVA_LIBRARIES := \ -    SystemUI-tags \ -    SystemUI-proto - -LOCAL_JAVA_LIBRARIES := telephony-common \ -    android.car - -LOCAL_PACKAGE_NAME := SystemUI -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform -LOCAL_PRIVILEGED_MODULE := true - -LOCAL_PROGUARD_FLAG_FILES := proguard.flags -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res-keyguard $(LOCAL_PATH)/res - -ifneq ($(INCREMENTAL_BUILDS),) -    LOCAL_PROGUARD_ENABLED := disabled -    LOCAL_JACK_ENABLED := incremental -    LOCAL_DX_FLAGS := --multi-dex -    LOCAL_JACK_FLAGS := --multi-dex native -endif - -include frameworks/base/packages/SettingsLib/common.mk - -LOCAL_AAPT_FLAGS := --extra-packages com.android.keyguard - -include $(BUILD_PACKAGE) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp new file mode 100644 index 000000000000..b38059de0f8d --- /dev/null +++ b/packages/SystemUI/plugin/Android.bp @@ -0,0 +1,37 @@ +// 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. + +java_library { + +    name: "SystemUIPluginLib", + +    srcs: ["src/**/*.java"], + + +} + +android_app { + +    // Dummy to generate .toc files. +    name: "PluginDummyLib", +    platform_apis: true, +    srcs: ["src/**/*.java"], + +    libs: ["SystemUIPluginLib"], + +    optimize: { +        enabled: false, +    }, + +} diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk deleted file mode 100644 index 8634684087e2..000000000000 --- a/packages/SystemUI/plugin/Android.mk +++ /dev/null @@ -1,42 +0,0 @@ -# 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. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_USE_AAPT2 := true - -LOCAL_MODULE_TAGS := optional - -LOCAL_MODULE := SystemUIPluginLib - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_JAR_EXCLUDE_FILES := none - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(CLEAR_VARS) - -# Dummy to generate .toc files. -LOCAL_PACKAGE_NAME := PluginDummyLib -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_JAVA_LIBRARIES := SystemUIPluginLib - -LOCAL_PROGUARD_ENABLED := disabled - -include $(BUILD_PACKAGE) diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.bp b/packages/SystemUI/plugin/ExamplePlugin/Android.bp new file mode 100644 index 000000000000..a0eaf14f4a06 --- /dev/null +++ b/packages/SystemUI/plugin/ExamplePlugin/Android.bp @@ -0,0 +1,14 @@ +android_app { + +    name: "ExamplePlugin", + +    libs: ["SystemUIPluginLib"], + +    certificate: "platform", +    optimize: { +        enabled: false, +    }, + +    srcs: ["src/**/*.java"], + +} diff --git a/packages/SystemUI/plugin/ExamplePlugin/Android.mk b/packages/SystemUI/plugin/ExamplePlugin/Android.mk deleted file mode 100644 index 4c82c7505ad3..000000000000 --- a/packages/SystemUI/plugin/ExamplePlugin/Android.mk +++ /dev/null @@ -1,15 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_USE_AAPT2 := true - -LOCAL_PACKAGE_NAME := ExamplePlugin - -LOCAL_JAVA_LIBRARIES := SystemUIPluginLib - -LOCAL_CERTIFICATE := platform -LOCAL_PROGUARD_ENABLED := disabled - -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -include $(BUILD_PACKAGE) diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 61f7fe8dc019..bf4374acf6e6 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -43,7 +43,7 @@ public interface QSTile {      boolean isAvailable();      void setTileSpec(String tileSpec); -    void clearState(); +    @Deprecated default void clearState() {}      void refreshState();      void addCallback(Callback callback); diff --git a/packages/SystemUI/res-keyguard/values/alias.xml b/packages/SystemUI/res-keyguard/values/alias.xml index f06b450c7dbe..1c63c7933faf 100644 --- a/packages/SystemUI/res-keyguard/values/alias.xml +++ b/packages/SystemUI/res-keyguard/values/alias.xml @@ -25,9 +25,6 @@      <!-- Alias used to reference framework "OK" string in keyguard.  -->      <item type="string" name="ok">@*android:string/ok</item> -    <!-- Alias used to reference framework "OK" string in keyguard.  --> -    <item type="string" name="system_ui_date_pattern">@*android:string/system_ui_date_pattern</item> -      <!-- Alias used to reference framework configuration for screen rotation.  -->      <item type="bool" name="config_enableLockScreenRotation">@*android:bool/config_enableLockScreenRotation</item> diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml index baaf699c278a..d72021e27e0b 100644 --- a/packages/SystemUI/res/layout/navigation_layout.xml +++ b/packages/SystemUI/res/layout/navigation_layout.xml @@ -18,14 +18,16 @@      xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:systemui="http://schemas.android.com/apk/res-auto"      android:layout_width="match_parent" -    android:layout_height="match_parent"> +    android:layout_height="match_parent" +    android:layout_marginStart="@dimen/rounded_corner_content_padding" +    android:layout_marginEnd="@dimen/rounded_corner_content_padding" +    android:paddingStart="@dimen/nav_content_padding" +    android:paddingEnd="@dimen/nav_content_padding">      <com.android.systemui.statusbar.phone.NearestTouchFrame          android:id="@+id/nav_buttons"          android:layout_width="match_parent"          android:layout_height="match_parent" -        android:paddingStart="@dimen/rounded_corner_content_padding" -        android:paddingEnd="@dimen/rounded_corner_content_padding"          android:clipChildren="false"          android:clipToPadding="false"> @@ -34,8 +36,6 @@              android:layout_width="match_parent"              android:layout_height="match_parent"              android:orientation="horizontal" -            android:paddingStart="@dimen/nav_content_padding" -            android:paddingEnd="@dimen/nav_content_padding"              android:clipToPadding="false"              android:clipChildren="false" /> @@ -46,8 +46,6 @@              android:layout_gravity="center"              android:gravity="center"              android:orientation="horizontal" -            android:paddingStart="@dimen/nav_content_padding" -            android:paddingEnd="@dimen/nav_content_padding"              android:clipToPadding="false"              android:clipChildren="false" /> diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml index 6d5b77885a09..24a0c71f3bad 100644 --- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml +++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml @@ -18,14 +18,16 @@      xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:systemui="http://schemas.android.com/apk/res-auto"      android:layout_width="match_parent" -    android:layout_height="match_parent"> +    android:layout_height="match_parent" +    android:layout_marginTop="@dimen/rounded_corner_content_padding" +    android:layout_marginBottom="@dimen/rounded_corner_content_padding" +    android:paddingTop="@dimen/nav_content_padding" +    android:paddingBottom="@dimen/nav_content_padding">      <com.android.systemui.statusbar.phone.NearestTouchFrame          android:id="@+id/nav_buttons"          android:layout_width="match_parent"          android:layout_height="match_parent" -        android:paddingTop="@dimen/rounded_corner_content_padding" -        android:paddingBottom="@dimen/rounded_corner_content_padding"          android:clipChildren="false"          android:clipToPadding="false"> @@ -34,10 +36,8 @@              android:layout_width="match_parent"              android:layout_height="match_parent"              android:orientation="vertical" -            android:paddingTop="@dimen/nav_content_padding" -            android:paddingBottom="@dimen/nav_content_padding" -            android:clipChildren="false" -            android:clipToPadding="false" /> +            android:clipToPadding="false" +            android:clipChildren="false" />          <com.android.systemui.statusbar.phone.ReverseLinearLayout              android:id="@+id/center_group" @@ -45,10 +45,8 @@              android:layout_height="match_parent"              android:gravity="center"              android:orientation="vertical" -            android:paddingTop="@dimen/nav_content_padding" -            android:paddingBottom="@dimen/nav_content_padding" -            android:clipChildren="false" -            android:clipToPadding="false" /> +            android:clipToPadding="false" +            android:clipChildren="false" />      </com.android.systemui.statusbar.phone.NearestTouchFrame> diff --git a/packages/SystemUI/res/values-bg/donottranslate.xml b/packages/SystemUI/res/values-bg/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-bg/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-hu/donottranslate.xml b/packages/SystemUI/res/values-hu/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-hu/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-ja/donottranslate.xml b/packages/SystemUI/res/values-ja/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-ja/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-ko/donottranslate.xml b/packages/SystemUI/res/values-ko/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-ko/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-lt/donottranslate.xml b/packages/SystemUI/res/values-lt/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-lt/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-sw720dp/donottranslate.xml b/packages/SystemUI/res/values-sw720dp/donottranslate.xml deleted file mode 100644 index 09960673a53e..000000000000 --- a/packages/SystemUI/res/values-sw720dp/donottranslate.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2011, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  %1$s is DOW, %2$s is date. -         We show both (DOW on one line, then the date) but this can be overridden for locales as -         necessary. -         --> -    <string name="status_bar_date_formatter">%1$s\n%2$s</string> - -</resources> - diff --git a/packages/SystemUI/res/values-tr/donottranslate.xml b/packages/SystemUI/res/values-tr/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-tr/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-zh-rCN/donottranslate.xml b/packages/SystemUI/res/values-zh-rCN/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-zh-rCN/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values-zh-rTW/donottranslate.xml b/packages/SystemUI/res/values-zh-rTW/donottranslate.xml deleted file mode 100644 index dcf434db111b..000000000000 --- a/packages/SystemUI/res/values-zh-rTW/donottranslate.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/** - * Copyright (c) 2009, 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. - */ ---> -<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <!-- For formatting day of week and date in DateView.  Day of week precedes date by default, -         but this may be overridden on a per-locale basis if necessary. --> -    <string name="status_bar_date_formatter">%2$s\n%1$s</string> - -</resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index be80d52f2a57..79e1fae98c21 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -943,9 +943,9 @@      <dimen name="bottom_padding">48dp</dimen>      <dimen name="edge_margin">8dp</dimen> -    <dimen name="rounded_corner_radius">0dp</dimen> -    <dimen name="rounded_corner_radius_top">0dp</dimen> -    <dimen name="rounded_corner_radius_bottom">0dp</dimen> +    <dimen name="rounded_corner_radius">@*android:dimen/rounded_corner_radius</dimen> +    <dimen name="rounded_corner_radius_top">@*android:dimen/rounded_corner_radius_top</dimen> +    <dimen name="rounded_corner_radius_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>      <dimen name="rounded_corner_content_padding">0dp</dimen>      <dimen name="nav_content_padding">0dp</dimen>      <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen> diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp new file mode 100644 index 000000000000..0fb12009e2cb --- /dev/null +++ b/packages/SystemUI/shared/Android.bp @@ -0,0 +1,40 @@ +// Copyright (C) 2017 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. + +android_library { + +    name: "SystemUISharedLib", +    srcs: [ +        "src/**/*.java", +        "src/**/I*.aidl", +    ], + +} + +android_app { + +    name: "SysUISharedLib", +    platform_apis: true, +    srcs: [ +        "src/**/*.java", +        "src/**/I*.aidl", +    ], + +    static_libs: ["SystemUISharedLib"], + +    optimize: { +        enabled: false, +    }, + +} diff --git a/packages/SystemUI/shared/Android.mk b/packages/SystemUI/shared/Android.mk deleted file mode 100644 index f20df0cebc8d..000000000000 --- a/packages/SystemUI/shared/Android.mk +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2017 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. - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_USE_AAPT2 := true - -LOCAL_MODULE_TAGS := optional - -LOCAL_MODULE := SystemUISharedLib - -LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src) - -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_JAR_EXCLUDE_FILES := none - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(CLEAR_VARS) - -LOCAL_PACKAGE_NAME := SysUISharedLib -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_JAVA_LIBRARIES := SystemUISharedLib - -LOCAL_PROGUARD_ENABLED := disabled - -include $(BUILD_PACKAGE) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk index 4e7cbbfede2b..02774c946596 100644 --- a/packages/SystemUI/shared/tests/Android.mk +++ b/packages/SystemUI/shared/tests/Android.mk @@ -30,10 +30,10 @@ LOCAL_PRIVATE_PLATFORM_APIS := true  LOCAL_COMPATIBILITY_SUITE := device-tests  # Add local path sources as well as shared lib sources -LOCAL_SRC_FILES := $(call all-java-files-under, src) \ -    $(call all-java-files-under, ../src) +LOCAL_SRC_FILES := $(call all-java-files-under, src)  LOCAL_STATIC_JAVA_LIBRARIES := \ +	SystemUISharedLib \      metrics-helper-lib \      android-support-test \      mockito-target-inline-minus-junit4 \ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 9e4810cb08ca..009ba4861af1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -15,7 +15,6 @@   */  package com.android.keyguard; -import android.R.style;  import android.app.Activity;  import android.app.AlertDialog;  import android.app.admin.DevicePolicyManager; @@ -26,7 +25,6 @@ import android.util.AttributeSet;  import android.util.Log;  import android.util.Slog;  import android.util.StatsLog; -import android.view.ContextThemeWrapper;  import android.view.LayoutInflater;  import android.view.View;  import android.view.WindowManager; @@ -142,6 +140,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe              mSecurityViewFlipper.addView(v);              updateSecurityView(v);              view = (KeyguardSecurityView)v; +            view.reset();          }          return view; @@ -209,7 +208,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe          if (messageId != 0) {              final String message = mContext.getString(messageId, -                    KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(userId), +                    mLockPatternUtils.getCurrentFailedPasswordAttempts(userId),                      timeoutInSeconds);              showDialog(null, message);          } @@ -254,8 +253,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe      }      private void reportFailedUnlockAttempt(int userId, int timeoutMs) { -        final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext); -        final int failedAttempts = monitor.getFailedUnlockAttempts(userId) + 1; // +1 for this time +        // +1 for this time +        final int failedAttempts = mLockPatternUtils.getCurrentFailedPasswordAttempts(userId) + 1;          if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts); @@ -289,7 +288,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe                  showWipeDialog(failedAttempts, userType);              }          } -        monitor.reportFailedStrongAuthUnlockAttempt(userId);          mLockPatternUtils.reportFailedPasswordAttempt(userId);          if (timeoutMs > 0) {              mLockPatternUtils.reportPasswordLockout(timeoutMs, userId); @@ -433,7 +431,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe              if (success) {                  StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED,                      StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS); -                monitor.clearFailedUnlockAttempts();                  mLockPatternUtils.reportSuccessfulPasswordAttempt(userId);              } else {                  StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index ef3aa42727e9..0e2181532630 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -209,9 +209,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {      // Battery status      private BatteryStatus mBatteryStatus; -    // Password attempts -    private SparseIntArray mFailedAttempts = new SparseIntArray(); -      private final StrongAuthTracker mStrongAuthTracker;      private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> @@ -1800,22 +1797,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {          return mDeviceProvisioned;      } -    public void clearFailedUnlockAttempts() { -        mFailedAttempts.delete(sCurrentUser); -    } -      public ServiceState getServiceState(int subId) {          return mServiceStates.get(subId);      } -    public int getFailedUnlockAttempts(int userId) { -        return mFailedAttempts.get(userId, 0); -    } - -    public void reportFailedStrongAuthUnlockAttempt(int userId) { -        mFailedAttempts.put(userId, getFailedUnlockAttempts(userId) + 1); -    } -      public void clearFingerprintRecognized() {          mUserFingerprintAuthenticated.clear();          mTrustManager.clearAllFingerprints(); diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 79302f2aa2ff..16b54b4cea5b 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -39,10 +39,13 @@ import android.graphics.PixelFormat;  import android.graphics.Rect;  import android.graphics.Region;  import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.os.HandlerThread;  import android.os.SystemProperties;  import android.provider.Settings.Secure;  import androidx.annotation.VisibleForTesting;  import android.util.DisplayMetrics; +import android.util.Log;  import android.view.DisplayCutout;  import android.view.DisplayInfo;  import android.view.Gravity; @@ -57,6 +60,7 @@ import android.view.WindowManager;  import android.widget.FrameLayout;  import android.widget.ImageView; +import com.android.internal.util.Preconditions;  import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;  import com.android.systemui.fragments.FragmentHostManager;  import com.android.systemui.fragments.FragmentHostManager.FragmentListener; @@ -74,6 +78,9 @@ import com.android.systemui.util.leak.RotationUtils;   * for antialiasing and emulation purposes.   */  public class ScreenDecorations extends SystemUI implements Tunable { +    private static final boolean DEBUG = false; +    private static final String TAG = "ScreenDecorations"; +      public static final String SIZE = "sysui_rounded_size";      public static final String PADDING = "sysui_rounded_content_padding";      private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = @@ -82,9 +89,9 @@ public class ScreenDecorations extends SystemUI implements Tunable {      private DisplayManager mDisplayManager;      private DisplayManager.DisplayListener mDisplayListener; -    private int mRoundedDefault; -    private int mRoundedDefaultTop; -    private int mRoundedDefaultBottom; +    @VisibleForTesting protected int mRoundedDefault; +    @VisibleForTesting protected int mRoundedDefaultTop; +    @VisibleForTesting protected int mRoundedDefaultBottom;      private View mOverlay;      private View mBottomOverlay;      private float mDensity; @@ -93,26 +100,30 @@ public class ScreenDecorations extends SystemUI implements Tunable {      private DisplayCutoutView mCutoutTop;      private DisplayCutoutView mCutoutBottom;      private boolean mPendingRotationChange; +    private Handler mHandler;      @Override      public void start() { +        mHandler = startHandlerThread(); +        mHandler.post(this::startOnScreenDecorationsThread); +        setupStatusBarPaddingIfNeeded(); +    } + +    @VisibleForTesting +    Handler startHandlerThread() { +        HandlerThread thread = new HandlerThread("ScreenDecorations"); +        thread.start(); +        return thread.getThreadHandler(); +    } + +    private void startOnScreenDecorationsThread() { +        mRotation = RotationUtils.getExactRotation(mContext);          mWindowManager = mContext.getSystemService(WindowManager.class); -        mRoundedDefault = mContext.getResources().getDimensionPixelSize( -                R.dimen.rounded_corner_radius); -        mRoundedDefaultTop = mContext.getResources().getDimensionPixelSize( -                R.dimen.rounded_corner_radius_top); -        mRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( -                R.dimen.rounded_corner_radius_bottom); +        updateRoundedCornerRadii();          if (hasRoundedCorners() || shouldDrawCutout()) {              setupDecorations();          } -        int padding = mContext.getResources().getDimensionPixelSize( -                R.dimen.rounded_corner_content_padding); -        if (padding != 0) { -            setupPadding(padding); -        } -          mDisplayListener = new DisplayManager.DisplayListener() {              @Override              public void onDisplayAdded(int displayId) { @@ -126,8 +137,8 @@ public class ScreenDecorations extends SystemUI implements Tunable {              @Override              public void onDisplayChanged(int displayId) { -                if (mOverlay != null && mBottomOverlay != null -                        && mRotation != RotationUtils.getExactRotation(mContext)) { +                final int newRotation = RotationUtils.getExactRotation(mContext); +                if (mOverlay != null && mBottomOverlay != null && mRotation != newRotation) {                      // We cannot immediately update the orientation. Otherwise                      // WindowManager is still deferring layout until it has finished dispatching                      // the config changes, which may cause divergence between what we draw @@ -136,20 +147,24 @@ public class ScreenDecorations extends SystemUI implements Tunable {                      // - we are trying to redraw. This because WM resized our window and told us to.                      // - the config change has been dispatched, so WM is no longer deferring layout.                      mPendingRotationChange = true; +                    if (DEBUG) { +                        Log.i(TAG, "Rotation changed, deferring " + newRotation + ", staying at " +                                + mRotation); +                    } +                      mOverlay.getViewTreeObserver().addOnPreDrawListener( -                            new RestartingPreDrawListener(mOverlay)); +                            new RestartingPreDrawListener(mOverlay, newRotation));                      mBottomOverlay.getViewTreeObserver().addOnPreDrawListener( -                            new RestartingPreDrawListener(mBottomOverlay)); - +                            new RestartingPreDrawListener(mBottomOverlay, newRotation));                  }                  updateOrientation();              }          }; -        mRotation = -1;          mDisplayManager = (DisplayManager) mContext.getSystemService(                  Context.DISPLAY_SERVICE); -        mDisplayManager.registerDisplayListener(mDisplayListener, null); +        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); +        updateOrientation();      }      private void setupDecorations() { @@ -179,10 +194,11 @@ public class ScreenDecorations extends SystemUI implements Tunable {          mWindowManager.getDefaultDisplay().getMetrics(metrics);          mDensity = metrics.density; -        Dependency.get(TunerService.class).addTunable(this, SIZE); +        Dependency.get(Dependency.MAIN_HANDLER).post( +                () -> Dependency.get(TunerService.class).addTunable(this, SIZE));          // Watch color inversion and invert the overlay as needed. -        SecureSetting setting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER), +        SecureSetting setting = new SecureSetting(mContext, mHandler,                  Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {              @Override              protected void handleValueChanged(int value, boolean observedChange) { @@ -215,18 +231,38 @@ public class ScreenDecorations extends SystemUI implements Tunable {                          .start();              }          }); + +        mOverlay.getViewTreeObserver().addOnPreDrawListener( +                new ValidatingPreDrawListener(mOverlay)); +        mBottomOverlay.getViewTreeObserver().addOnPreDrawListener( +                new ValidatingPreDrawListener(mBottomOverlay));      }      @Override      protected void onConfigurationChanged(Configuration newConfig) { -        mPendingRotationChange = false; -        updateOrientation(); -        if (shouldDrawCutout() && mOverlay == null) { -            setupDecorations(); -        } +        mHandler.post(() -> { +            int oldRotation = mRotation; +            mPendingRotationChange = false; +            updateOrientation(); +            updateRoundedCornerRadii(); +            if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation); +            if (shouldDrawCutout() && mOverlay == null) { +                setupDecorations(); +            } +            if (mOverlay != null) { +                // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(), +                // which ensures that the forced seamless rotation will end, even if we updated +                // the rotation before window manager was ready (and was still waiting for sending +                // the updated rotation). +                updateLayoutParams(); +            } +        });      } -    protected void updateOrientation() { +    private void updateOrientation() { +        Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(), +                "must call on " + mHandler.getLooper().getThread() +                        + ", but was " + Thread.currentThread());          if (mPendingRotationChange) {              return;          } @@ -241,6 +277,26 @@ public class ScreenDecorations extends SystemUI implements Tunable {          }      } +    private void updateRoundedCornerRadii() { +        final int newRoundedDefault = mContext.getResources().getDimensionPixelSize( +                R.dimen.rounded_corner_radius); +        final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize( +                R.dimen.rounded_corner_radius_top); +        final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( +                R.dimen.rounded_corner_radius_bottom); + +        final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault +                || mRoundedDefaultBottom != newRoundedDefaultBottom +                || mRoundedDefaultTop != newRoundedDefaultTop; + +        if (roundedCornersChanged) { +            mRoundedDefault = newRoundedDefault; +            mRoundedDefaultTop = newRoundedDefaultTop; +            mRoundedDefaultBottom = newRoundedDefaultBottom; +            onTuningChanged(SIZE, null); +        } +    } +      private void updateViews() {          View topLeft = mOverlay.findViewById(R.id.left);          View topRight = mOverlay.findViewById(R.id.right); @@ -306,7 +362,19 @@ public class ScreenDecorations extends SystemUI implements Tunable {                  com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout);      } -    private void setupPadding(int padding) { + +    private void setupStatusBarPaddingIfNeeded() { +        // TODO: This should be moved to a more appropriate place, as it is not related to the +        // screen decorations overlay. +        int padding = mContext.getResources().getDimensionPixelSize( +                R.dimen.rounded_corner_content_padding); +        if (padding != 0) { +            setupStatusBarPadding(padding); +        } + +    } + +    private void setupStatusBarPadding(int padding) {          // Add some padding to all the content near the edge of the screen.          StatusBar sb = getComponent(StatusBar.class);          View statusBar = (sb != null ? sb.getStatusBarWindow() : null); @@ -375,30 +443,32 @@ public class ScreenDecorations extends SystemUI implements Tunable {      @Override      public void onTuningChanged(String key, String newValue) { -        if (mOverlay == null) return; -        if (SIZE.equals(key)) { -            int size = mRoundedDefault; -            int sizeTop = mRoundedDefaultTop; -            int sizeBottom = mRoundedDefaultBottom; -            if (newValue != null) { -                try { -                    size = (int) (Integer.parseInt(newValue) * mDensity); -                } catch (Exception e) { +        mHandler.post(() -> { +            if (mOverlay == null) return; +            if (SIZE.equals(key)) { +                int size = mRoundedDefault; +                int sizeTop = mRoundedDefaultTop; +                int sizeBottom = mRoundedDefaultBottom; +                if (newValue != null) { +                    try { +                        size = (int) (Integer.parseInt(newValue) * mDensity); +                    } catch (Exception e) { +                    }                  } -            } -            if (sizeTop == 0) { -                sizeTop = size; -            } -            if (sizeBottom == 0) { -                sizeBottom = size; -            } +                if (sizeTop == 0) { +                    sizeTop = size; +                } +                if (sizeBottom == 0) { +                    sizeBottom = size; +                } -            setSize(mOverlay.findViewById(R.id.left), sizeTop); -            setSize(mOverlay.findViewById(R.id.right), sizeTop); -            setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom); -            setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom); -        } +                setSize(mOverlay.findViewById(R.id.left), sizeTop); +                setSize(mOverlay.findViewById(R.id.right), sizeTop); +                setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom); +                setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom); +            } +        });      }      private void setSize(View view, int pixelSize) { @@ -457,6 +527,11 @@ public class ScreenDecorations extends SystemUI implements Tunable {              mVisibilityChangedListener = visibilityChangedListener;              mDecorations = decorations;              setId(R.id.display_cutout); +            if (DEBUG) { +                getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG, +                        (mInitialStart ? "OverlayTop" : "OverlayBottom") +                                + " drawn in rot " + mRotation)); +            }          }          public void setColor(int color) { @@ -692,20 +767,66 @@ public class ScreenDecorations extends SystemUI implements Tunable {      private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {          private final View mView; +        private final int mTargetRotation; -        private RestartingPreDrawListener(View view) { +        private RestartingPreDrawListener(View view, int targetRotation) {              mView = view; +            mTargetRotation = targetRotation;          }          @Override          public boolean onPreDraw() { -            mPendingRotationChange = false;              mView.getViewTreeObserver().removeOnPreDrawListener(this); + +            if (mTargetRotation == mRotation) { +                if (DEBUG) { +                    Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom") +                            + " already in target rot " +                            + mTargetRotation + ", allow draw without restarting it"); +                } +                return true; +            } + +            mPendingRotationChange = false;              // This changes the window attributes - we need to restart the traversal for them to              // take effect.              updateOrientation(); +            if (DEBUG) { +                Log.i(TAG, (mView == mOverlay ? "OverlayTop" : "OverlayBottom") +                        + " restarting listener fired, restarting draw for rot " + mRotation); +            }              mView.invalidate();              return false;          }      } + +    /** +     * A pre-draw listener, that validates that the rotation we draw in matches the displays +     * rotation before continuing the draw. +     * +     * This is to prevent a race condition, where we have not received the display changed event +     * yet, and would thus draw in an old orientation. +     */ +    private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener { + +        private final View mView; + +        public ValidatingPreDrawListener(View view) { +            mView = view; +        } + +        @Override +        public boolean onPreDraw() { +            final int displayRotation = RotationUtils.getExactRotation(mContext); +            if (displayRotation != mRotation && !mPendingRotationChange) { +                if (DEBUG) { +                    Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot " +                            + displayRotation + ". Restarting draw"); +                } +                mView.invalidate(); +                return false; +            } +            return true; +        } +    }  } diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java index f8b73a172516..d6472b7ddbb9 100644 --- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java +++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java @@ -101,31 +101,31 @@ public class SensorLoggerSession {      public Session toProto() {          Session proto = new Session(); -        proto.setStartTimestampMillis(mStartTimestampMillis); -        proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis); -        proto.setBuild(Build.FINGERPRINT); -        proto.setResult(mResult); -        proto.setType(mType); +        proto.startTimestampMillis = mStartTimestampMillis; +        proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis; +        proto.build = Build.FINGERPRINT; +        proto.result = mResult; +        proto.type = mType;          proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);          proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);          proto.phoneEvents = mPhoneEvents.toArray(proto.phoneEvents); -        proto.setTouchAreaWidth(mTouchAreaWidth); -        proto.setTouchAreaHeight(mTouchAreaHeight); +        proto.touchAreaWidth = mTouchAreaWidth; +        proto.touchAreaHeight = mTouchAreaHeight;          return proto;      }      private PhoneEvent phoneEventToProto(int eventType, long sysTimeNanos) {          PhoneEvent proto = new PhoneEvent(); -        proto.setType(eventType); -        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); +        proto.type = eventType; +        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos;          return proto;      }      private SensorEvent sensorEventToProto(android.hardware.SensorEvent ev, long sysTimeNanos) {          SensorEvent proto = new SensorEvent(); -        proto.setType(ev.sensor.getType()); -        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos); -        proto.setTimestamp(ev.timestamp); +        proto.type = ev.sensor.getType(); +        proto.timeOffsetNanos = sysTimeNanos - mStartSystemTimeNanos; +        proto.timestamp = ev.timestamp;          proto.values = ev.values.clone();          return proto;      } @@ -133,17 +133,17 @@ public class SensorLoggerSession {      private TouchEvent motionEventToProto(MotionEvent ev) {          int count = ev.getPointerCount();          TouchEvent proto = new TouchEvent(); -        proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos); -        proto.setAction(ev.getActionMasked()); -        proto.setActionIndex(ev.getActionIndex()); +        proto.timeOffsetNanos = ev.getEventTimeNano() - mStartSystemTimeNanos; +        proto.action = ev.getActionMasked(); +        proto.actionIndex = ev.getActionIndex();          proto.pointers = new TouchEvent.Pointer[count];          for (int i = 0; i < count; i++) {              TouchEvent.Pointer p = new TouchEvent.Pointer(); -            p.setX(ev.getX(i)); -            p.setY(ev.getY(i)); -            p.setSize(ev.getSize(i)); -            p.setPressure(ev.getPressure(i)); -            p.setId(ev.getPointerId(i)); +            p.x = ev.getX(i); +            p.y = ev.getY(i); +            p.size = ev.getSize(i); +            p.pressure = ev.getPressure(i); +            p.id = ev.getPointerId(i);              proto.pointers[i] = p;          }          return proto; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 89688fba1cc6..33db2c8bc16f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -1647,7 +1647,6 @@ public class KeyguardViewMediator extends SystemUI {              resetKeyguardDonePendingLocked();          } -        mUpdateMonitor.clearFailedUnlockAttempts();          mUpdateMonitor.clearFingerprintRecognized();          if (mGoingToSleep) { diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index da41136767aa..2e5eb342347b 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -266,9 +266,12 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {                  || mEstimate.estimateMillis < mSevereWarningThreshold) {              nb.setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));          } -        nb.addAction(0, -                mContext.getString(R.string.battery_saver_start_action), -                pendingBroadcast(ACTION_START_SAVER)); + +        if (!mPowerMan.isPowerSaveMode()) { +            nb.addAction(0, +                    mContext.getString(R.string.battery_saver_start_action), +                    pendingBroadcast(ACTION_START_SAVER)); +        }          nb.setOnlyAlertOnce(!mPlaySound);          mPlaySound = false;          SystemUI.overrideNotificationAppName(mContext, nb, false); diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 9a648d17c4ff..0b9067e5dc1f 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -333,10 +333,11 @@ public class PowerUI extends SystemUI {      @VisibleForTesting      boolean shouldDismissLowBatteryWarning(boolean plugged, int oldBucket, int bucket,              long timeRemaining, boolean isPowerSaver) { -        final boolean hybridWouldDismiss = mEnhancedEstimates.isHybridNotificationEnabled() +        final boolean hybridEnabled = mEnhancedEstimates.isHybridNotificationEnabled(); +        final boolean hybridWouldDismiss = hybridEnabled                  && timeRemaining > mEnhancedEstimates.getLowWarningThreshold();          final boolean standardWouldDismiss = (bucket > oldBucket && bucket > 0); -        return isPowerSaver +        return (isPowerSaver && !hybridEnabled)                  || plugged                  || (standardWouldDismiss && (!mEnhancedEstimates.isHybridNotificationEnabled()                          || hybridWouldDismiss)); @@ -344,14 +345,14 @@ public class PowerUI extends SystemUI {      private boolean isEnhancedTrigger(boolean plugged, long timeRemaining, boolean isPowerSaver,              int batteryStatus) { -        if (plugged || isPowerSaver || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) { +        if (plugged || batteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN) {              return false;          }          int warnLevel = mLowBatteryReminderLevels[0];          int critLevel = mLowBatteryReminderLevels[1]; -        // Only show the low warning once per charge cycle -        final boolean canShowWarning = !mLowWarningShownThisChargeCycle +        // Only show the low warning once per charge cycle & no battery saver +        final boolean canShowWarning = !mLowWarningShownThisChargeCycle && !isPowerSaver                  && (timeRemaining < mEnhancedEstimates.getLowWarningThreshold()                          || mBatteryLevel <= warnLevel); diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java index a1c25772234e..87c64c78edc8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java @@ -47,16 +47,12 @@ public class PseudoGridView extends ViewGroup {          final int N = a.getIndexCount();          for (int i = 0; i < N; i++) {              int attr = a.getIndex(i); -            switch (attr) { -                case R.styleable.PseudoGridView_numColumns: -                    mNumColumns = a.getInt(attr, 3); -                    break; -                case R.styleable.PseudoGridView_verticalSpacing: -                    mVerticalSpacing = a.getDimensionPixelSize(attr, 0); -                    break; -                case R.styleable.PseudoGridView_horizontalSpacing: -                    mHorizontalSpacing = a.getDimensionPixelSize(attr, 0); -                    break; +            if (attr == R.styleable.PseudoGridView_numColumns) { +                mNumColumns = a.getInt(attr, 3); +            } else if (attr == R.styleable.PseudoGridView_verticalSpacing) { +                mVerticalSpacing = a.getDimensionPixelSize(attr, 0); +            } else if (attr == R.styleable.PseudoGridView_horizontalSpacing) { +                mHorizontalSpacing = a.getDimensionPixelSize(attr, 0);              }          } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 0876a5d3f456..3fc258b1e8e9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -285,9 +285,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne          updatePageIndicator(); -        for (TileRecord r : mRecords) { -            r.tile.clearState(); -        }          if (mListening) {              refreshAllTiles();          } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 53a576d3519d..591e9e015897 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -95,7 +95,6 @@ public class TileQueryHelper {                  continue;              }              tile.setListening(this, true); -            tile.clearState();              tile.refreshState();              tile.setListening(this, false);              tile.setTileSpec(spec); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 834feb7781ea..022a2b4a5fbf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -211,10 +211,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {          mHandler.obtainMessage(H.REFRESH_STATE, arg).sendToTarget();      } -    public void clearState() { -        mHandler.sendEmptyMessage(H.CLEAR_STATE); -    } -      public void userSwitch(int newUserId) {          mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget();      } @@ -266,11 +262,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {      public abstract Intent getLongClickIntent(); -    protected void handleClearState() { -        mTmpState = newTileState(); -        mState = newTileState(); -    } -      protected void handleRefreshState(Object arg) {          handleUpdateState(mTmpState, arg);          final boolean changed = mTmpState.copyTo(mState); @@ -409,11 +400,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {          private static final int TOGGLE_STATE_CHANGED = 8;          private static final int SCAN_STATE_CHANGED = 9;          private static final int DESTROY = 10; -        private static final int CLEAR_STATE = 11; -        private static final int REMOVE_CALLBACKS = 12; -        private static final int REMOVE_CALLBACK = 13; -        private static final int SET_LISTENING = 14; -        private static final int STALE = 15; +        private static final int REMOVE_CALLBACKS = 11; +        private static final int REMOVE_CALLBACK = 12; +        private static final int SET_LISTENING = 13; +        private static final int STALE = 14;          @VisibleForTesting          protected H(Looper looper) { @@ -467,9 +457,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {                  } else if (msg.what == DESTROY) {                      name = "handleDestroy";                      handleDestroy(); -                } else if (msg.what == CLEAR_STATE) { -                    name = "handleClearState"; -                    handleClearState();                  } else if (msg.what == SET_LISTENING) {                      name = "handleSetListeningInternal";                      handleSetListeningInternal(msg.obj, msg.arg1 != 0); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java index 1e9a618c3324..ad7d1b6b4689 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java @@ -69,13 +69,10 @@ public class UserDetailItemView extends LinearLayout {          final int N = a.getIndexCount();          for (int i = 0; i < N; i++) {              int attr = a.getIndex(i); -            switch (attr) { -                case R.styleable.UserDetailItemView_regularFontFamily: -                    mRegularTypeface = Typeface.create(a.getString(attr), 0 /* style */); -                    break; -                case R.styleable.UserDetailItemView_activatedFontFamily: -                    mActivatedTypeface = Typeface.create(a.getString(attr), 0 /* style */); -                    break; +            if (attr == R.styleable.UserDetailItemView_regularFontFamily) { +                mRegularTypeface = Typeface.create(a.getString(attr), 0 /* style */); +            } else if (attr == R.styleable.UserDetailItemView_activatedFontFamily) { +                mActivatedTypeface = Typeface.create(a.getString(attr), 0 /* style */);              }          }          a.recycle(); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 3eb3160b028f..98925b9ba9e5 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -226,22 +226,16 @@ public class DividerView extends FrameLayout implements OnTouchListener,          public boolean performAccessibilityAction(View host, int action, Bundle args) {              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 (action == R.id.action_move_tl_full) { +                nextTarget = mSnapAlgorithm.getDismissEndTarget(); +            } else if (action == R.id.action_move_tl_70) { +                nextTarget = mSnapAlgorithm.getLastSplitTarget(); +            } else if (action == R.id.action_move_tl_50) { +                nextTarget = mSnapAlgorithm.getMiddleTarget(); +            } else if (action == R.id.action_move_tl_30) { +                nextTarget = mSnapAlgorithm.getFirstSplitTarget(); +            } else if (action == R.id.action_move_rb_full) { +                nextTarget = mSnapAlgorithm.getDismissStartTarget();              }              if (nextTarget != null) {                  startDragging(true /* animate */, false /* touching */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index d647e21888dd..29687228902f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -2747,16 +2747,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView              case AccessibilityNodeInfo.ACTION_LONG_CLICK:                  doLongClickCallback();                  return true; -            case R.id.action_snooze: -                NotificationMenuRowPlugin provider = getProvider(); -                if (provider == null) { -                    provider = createMenu(); +            default: +                if (action == R.id.action_snooze) { +                    NotificationMenuRowPlugin provider = getProvider(); +                    if (provider == null) { +                        provider = createMenu(); +                    } +                    MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext()); +                    if (snoozeMenu != null) { +                        doLongClickCallback(getWidth() / 2, getHeight() / 2, snoozeMenu); +                    } +                    return true;                  } -                MenuItem snoozeMenu = provider.getSnoozeMenuItem(getContext()); -                if (snoozeMenu != null) { -                    doLongClickCallback(getWidth() / 2, getHeight() / 2, snoozeMenu); -                } -                return true;          }          return false;      } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java index 06f26c9cbc7c..469c3c2c60b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java @@ -667,9 +667,15 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.                      entry.row.getNotificationChildren();              for (int i = 0; i < notificationChildren.size(); i++) {                  ExpandableNotificationRow row = notificationChildren.get(i); -                if ((row.getStatusBarNotification().getNotification().flags -                        & Notification.FLAG_FOREGROUND_SERVICE) != 0) { -                    // the child is a foreground service notification which we can't remove! +                NotificationData.Entry childEntry = row.getEntry(); +                boolean isForeground = (row.getStatusBarNotification().getNotification().flags +                        & Notification.FLAG_FOREGROUND_SERVICE) != 0; +                boolean keepForReply = FORCE_REMOTE_INPUT_HISTORY +                        && (shouldKeepForRemoteInput(childEntry) +                                || shouldKeepForSmartReply(childEntry)); +                if (isForeground || keepForReply) { +                    // the child is a foreground service notification which we can't remove or it's +                    // a child we're keeping around for reply!                      continue;                  }                  row.setKeepInParent(true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 306319903ecb..a215ec6ecafa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -151,12 +151,11 @@ public class NotificationShelf extends ActivatableNotificationView implements      }      public void fadeInTranslating() { -        float translation = mShelfIcons.getTranslationY(); -        mShelfIcons.setTranslationY(translation - mShelfAppearTranslation); +        mShelfIcons.setTranslationY(-mShelfAppearTranslation);          mShelfIcons.setAlpha(0);          mShelfIcons.animate()                  .setInterpolator(Interpolators.DECELERATE_QUINT) -                .translationY(translation) +                .translationY(0)                  .setDuration(SHELF_IN_TRANSLATION_DURATION)                  .start();          mShelfIcons.animate() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 8aebd611344a..d2ffdbf11e26 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -256,13 +256,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav          @Override          public boolean performAccessibilityAction(View host, int action, Bundle args) { -            switch (action) { -                case R.id.action_toggle_overview: -                    SysUiServiceProvider.getComponent(getContext(), Recents.class) -                            .toggleRecentApps(); -                    break; -                default: -                    return super.performAccessibilityAction(host, action, args); +            if (action == R.id.action_toggle_overview) { +                SysUiServiceProvider.getComponent(getContext(), Recents.class) +                        .toggleRecentApps(); +            } else { +                return super.performAccessibilityAction(host, action, args);              }              return true;          } 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 7e6abe95e226..5c18782727df 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1358,9 +1358,7 @@ public class NotificationPanelView extends PanelView implements          mQsExpansionHeight = height;          updateQsExpansion();          requestScrollerTopPaddingUpdate(false /* animate */); -        if (mKeyguardShowing) { -            updateHeaderKeyguardAlpha(); -        } +        updateHeaderKeyguardAlpha();          if (mStatusBarState == StatusBarState.SHADE_LOCKED                  || mStatusBarState == StatusBarState.KEYGUARD) {              updateKeyguardBottomAreaAlpha(); @@ -1763,6 +1761,9 @@ public class NotificationPanelView extends PanelView implements      }      private void updateHeaderKeyguardAlpha() { +        if (!mKeyguardShowing) { +            return; +        }          float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);          mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)                  * mKeyguardStatusBarAnimateAlpha); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index bd73a4064908..d68e2fa34cbc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -189,7 +189,7 @@ public class QuickStepController implements GestureHelper {                  mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE;          if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()                  && !mNavigationBarView.isQuickStepSwipeUpEnabled())) { -            return false; +            return deadZoneConsumed;          }          mNavigationBarView.requestUnbufferedDispatch(event); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index fadc0eac9e73..a38328a8161e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -180,6 +180,15 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D          mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;      } +    private void applyExpandedFlag(State state) { +        if (state.panelExpanded || state.isKeyguardShowingAndNotOccluded() || state.bouncerShowing +                || ENABLE_REMOTE_INPUT && state.remoteInputActive) { +            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; +        } else { +            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED; +        } +    } +      private void applyHeight(State state) {          boolean expanded = isExpanded(state);          if (state.forcePluginOpen) { @@ -234,6 +243,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D          applyKeyguardFlags(state);          applyForceStatusBarVisibleFlag(state);          applyFocusableFlag(state); +        applyExpandedFlag(state);          adjustScreenOrientation(state);          applyHeight(state);          applyUserActivityTimeout(state); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java index dc1b35d6c701..2ed2edb969bd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java @@ -45,25 +45,18 @@ public class UserAvatarView extends View {          final int N = a.getIndexCount();          for (int i = 0; i < N; i++) {              int attr = a.getIndex(i); -            switch (attr) { -                case R.styleable.UserAvatarView_avatarPadding: -                    setAvatarPadding(a.getDimension(attr, 0)); -                    break; -                case R.styleable.UserAvatarView_frameWidth: -                    setFrameWidth(a.getDimension(attr, 0)); -                    break; -                case R.styleable.UserAvatarView_framePadding: -                    setFramePadding(a.getDimension(attr, 0)); -                    break; -                case R.styleable.UserAvatarView_frameColor: -                    setFrameColor(a.getColorStateList(attr)); -                    break; -                case R.styleable.UserAvatarView_badgeDiameter: -                    setBadgeDiameter(a.getDimension(attr, 0)); -                    break; -                case R.styleable.UserAvatarView_badgeMargin: -                    setBadgeMargin(a.getDimension(attr, 0)); -                    break; +            if (attr == R.styleable.UserAvatarView_avatarPadding) { +                setAvatarPadding(a.getDimension(attr, 0)); +            } else if (attr == R.styleable.UserAvatarView_frameWidth) { +                setFrameWidth(a.getDimension(attr, 0)); +            } else if (attr == R.styleable.UserAvatarView_framePadding) { +                setFramePadding(a.getDimension(attr, 0)); +            } else if (attr == R.styleable.UserAvatarView_frameColor) { +                setFrameColor(a.getColorStateList(attr)); +            } else if (attr == R.styleable.UserAvatarView_badgeDiameter) { +                setBadgeDiameter(a.getDimension(attr, 0)); +            } else if (attr == R.styleable.UserAvatarView_badgeMargin) { +                setBadgeMargin(a.getDimension(attr, 0));              }          }          a.recycle(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index d6d0673e2c0b..3c16329e6f19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -134,6 +134,10 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof      @Override      public void setHotspotEnabled(boolean enabled) { +        if (mWaitingForCallback) { +            if (DEBUG) Log.d(TAG, "Ignoring setHotspotEnabled; waiting for callback."); +            return; +        }          if (enabled) {              OnStartTetheringCallback callback = new OnStartTetheringCallback();              mWaitingForCallback = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 924aa0120c94..d43dc810cfb5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -127,19 +127,14 @@ public class SmartReplyView extends ViewGroup {          final int length = arr.getIndexCount();          for (int i = 0; i < length; i++) {              int attr = arr.getIndex(i); -            switch (attr) { -                case R.styleable.SmartReplyView_spacing: -                    spacing = arr.getDimensionPixelSize(i, 0); -                    break; -                case R.styleable.SmartReplyView_singleLineButtonPaddingHorizontal: -                    singleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0); -                    break; -                case R.styleable.SmartReplyView_doubleLineButtonPaddingHorizontal: -                    doubleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0); -                    break; -                case R.styleable.SmartReplyView_buttonStrokeWidth: -                    strokeWidth = arr.getDimensionPixelSize(i, 0); -                    break; +            if (attr == R.styleable.SmartReplyView_spacing) { +                spacing = arr.getDimensionPixelSize(i, 0); +            } else if (attr == R.styleable.SmartReplyView_singleLineButtonPaddingHorizontal) { +                singleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0); +            } else if (attr == R.styleable.SmartReplyView_doubleLineButtonPaddingHorizontal) { +                doubleLineButtonPaddingHorizontal = arr.getDimensionPixelSize(i, 0); +            } else if (attr == R.styleable.SmartReplyView_buttonStrokeWidth) { +                strokeWidth = arr.getDimensionPixelSize(i, 0);              }          }          arr.recycle(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java index d7c4bbf3ea1d..c97095e1860b 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java @@ -21,11 +21,13 @@ import android.content.Context;  import android.content.DialogInterface;  import android.content.Intent;  import android.content.IntentFilter; +import android.content.res.Resources.NotFoundException;  import android.media.AudioManager;  import android.util.Log;  import android.view.KeyEvent;  import android.view.WindowManager; +  import com.android.systemui.statusbar.phone.SystemUIDialog;  abstract public class SafetyWarningDialog extends SystemUIDialog @@ -40,12 +42,18 @@ abstract public class SafetyWarningDialog extends SystemUIDialog      private long mShowTime;      private boolean mNewVolumeUp; +    private boolean mDisableOnVolumeUp;      public SafetyWarningDialog(Context context, AudioManager audioManager) {          super(context);          mContext = context;          mAudioManager = audioManager; - +        try { +            mDisableOnVolumeUp = mContext.getResources().getBoolean( +                  com.android.internal.R.bool.config_safe_media_disable_on_volume_up); +        } catch (NotFoundException e) { +            mDisableOnVolumeUp = true; +        }          getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);          setShowForAllUsers(true);          setMessage(mContext.getString(com.android.internal.R.string.safe_media_volume_warning)); @@ -63,7 +71,8 @@ abstract public class SafetyWarningDialog extends SystemUIDialog      @Override      public boolean onKeyDown(int keyCode, KeyEvent event) { -        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && event.getRepeatCount() == 0) { +        if (mDisableOnVolumeUp && keyCode == KeyEvent.KEYCODE_VOLUME_UP +            && event.getRepeatCount() == 0) {              mNewVolumeUp = true;          }          return super.onKeyDown(keyCode, event); diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index a4120c45a83a..9ee55324efa2 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -30,37 +30,17 @@ LOCAL_PRIVATE_PLATFORM_APIS := true  LOCAL_COMPATIBILITY_SUITE := device-tests  LOCAL_SRC_FILES := $(call all-java-files-under, src) \ -    $(call all-Iaidl-files-under, src) \ -    $(call all-java-files-under, ../src) +    $(call all-Iaidl-files-under, src) -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \ -    frameworks/base/packages/SystemUI/res \ -    frameworks/base/packages/SystemUI/res-keyguard \ +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res  LOCAL_STATIC_ANDROID_LIBRARIES := \ -    SystemUIPluginLib \ -    SystemUISharedLib \ -    androidx.car_car \ -    androidx.legacy_legacy-support-v4 \ -    androidx.recyclerview_recyclerview \ -    androidx.preference_preference \ -    androidx.appcompat_appcompat \ -    androidx.mediarouter_mediarouter \ -    androidx.palette_palette \ -    androidx.legacy_legacy-preference-v14 \ -    androidx.leanback_leanback \ -    androidx.slice_slice-core \ -    androidx.slice_slice-view \ -    androidx.slice_slice-builders \ -    androidx.arch.core_core-runtime \ -    androidx.lifecycle_lifecycle-extensions \ +    SystemUI-core  LOCAL_STATIC_JAVA_LIBRARIES := \      metrics-helper-lib \      android-support-test \      mockito-target-inline-minus-junit4 \ -    SystemUI-proto \ -    SystemUI-tags \      testables \      truth-prebuilt \ @@ -70,7 +50,6 @@ LOCAL_JNI_SHARED_LIBRARIES := \      libdexmakerjvmtiagent \      libmultiplejvmtiagentsinterferenceagent -  LOCAL_JAVA_LIBRARIES := \      android.test.runner \      telephony-common \ @@ -112,8 +91,6 @@ jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))  LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*  LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := com.android.systemui.tests.*,$(jacoco_exclude) -include frameworks/base/packages/SettingsLib/common.mk -  ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)      include $(BUILD_PACKAGE)  endif diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index 1be83229cf22..36ffebaef564 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -15,6 +15,8 @@  -->  <manifest xmlns:android="http://schemas.android.com/apk/res/android" +    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" +    xmlns:tools="http://schemas.android.com/tools"      package="com.android.systemui.tests">      <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> @@ -63,6 +65,19 @@                  <action android:name="com.android.systemui.action.TEST_ACTION" />              </intent-filter>          </receiver> + +        <provider android:name="com.android.systemui.keyguard.KeyguardSliceProvider" +            android:authorities="com.android.systemui.test.keyguard.disabled" +            android:enabled="false" +            tools:replace="android:authorities" +            tools:node="remove" /> + +        <provider +            android:name="androidx.core.content.FileProvider" +            android:authorities="com.android.systemui.test.fileprovider" +            android:exported="false" +            tools:replace="android:authorities" +            android:grantUriPermissions="true" />      </application>      <instrumentation android:name="android.testing.TestableInstrumentation" diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index f1bf31d7a58a..cc969177ab2e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -21,6 +21,7 @@ import static com.android.systemui.tuner.TunablePadding.FLAG_START;  import static org.hamcrest.Matchers.is;  import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals;  import static org.mockito.ArgumentMatchers.any;  import static org.mockito.ArgumentMatchers.anyInt;  import static org.mockito.ArgumentMatchers.anyString; @@ -34,8 +35,10 @@ import static org.mockito.Mockito.when;  import android.app.Fragment;  import android.content.res.Configuration; +import android.os.Handler;  import android.support.test.filters.SmallTest;  import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper;  import android.testing.TestableLooper.RunWithLooper;  import android.view.Display;  import android.view.View; @@ -60,6 +63,7 @@ import org.junit.runner.RunWith;  @SmallTest  public class ScreenDecorationsTest extends SysuiTestCase { +    private TestableLooper mTestableLooper;      private ScreenDecorations mScreenDecorations;      private StatusBar mStatusBar;      private WindowManager mWindowManager; @@ -71,6 +75,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {      @Before      public void setup() { +        mTestableLooper = TestableLooper.get(this); +        mDependency.injectTestDependency(Dependency.MAIN_HANDLER, +                new Handler(mTestableLooper.getLooper())); +          mStatusBar = mock(StatusBar.class);          mWindowManager = mock(WindowManager.class);          mView = spy(new StatusBarWindowView(mContext, null)); @@ -88,7 +96,31 @@ public class ScreenDecorationsTest extends SysuiTestCase {          mTunerService = mDependency.injectMockDependency(TunerService.class); -        mScreenDecorations = new ScreenDecorations(); + +        mScreenDecorations = new ScreenDecorations() { +            @Override +            public void start() { +                super.start(); +                mTestableLooper.processAllMessages(); +            } + +            @Override +            Handler startHandlerThread() { +                return new Handler(mTestableLooper.getLooper()); +            } + +            @Override +            protected void onConfigurationChanged(Configuration newConfig) { +                super.onConfigurationChanged(newConfig); +                mTestableLooper.processAllMessages(); +            } + +            @Override +            public void onTuningChanged(String key, String newValue) { +                super.onTuningChanged(key, newValue); +                mTestableLooper.processAllMessages(); +            } +        };          mScreenDecorations.mContext = mContext;          mScreenDecorations.mComponents = mContext.getComponents(); @@ -195,4 +227,17 @@ public class ScreenDecorationsTest extends SysuiTestCase {          verify(padding).destroy();      } +    @Test +    public void testUpdateRoundedCorners() { +        mContext.getOrCreateTestableResources().addOverride( +                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false); +        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20); + +        mScreenDecorations.start(); +        assertEquals(mScreenDecorations.mRoundedDefault, 20); + +        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 5); +        mScreenDecorations.onConfigurationChanged(null); +        assertEquals(mScreenDecorations.mRoundedDefault, 5); +    }  } diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 5ecf0c04aeb1..a9d49f91e44e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -323,9 +323,9 @@ public class PowerUITest extends SysuiTestCase {      }      @Test -    public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabled() { +    public void testShouldDismissLowBatteryWarning_dismissWhenPowerSaverEnabledLegacy() {          mPowerUI.start(); -        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); +        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(false);          when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS);          when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS); @@ -337,6 +337,20 @@ public class PowerUITest extends SysuiTestCase {      }      @Test +    public void testShouldNotDismissLowBatteryWarning_dismissWhenPowerSaverEnabledHybrid() { +        mPowerUI.start(); +        when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); +        when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS); +        when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS); + +        // device that gets power saver turned on should dismiss +        boolean shouldDismiss = +            mPowerUI.shouldDismissLowBatteryWarning(UNPLUGGED, BELOW_WARNING_BUCKET, +                BELOW_WARNING_BUCKET, ABOVE_HYBRID_THRESHOLD, !POWER_SAVER_OFF); +        assertFalse(shouldDismiss); +    } + +    @Test      public void testShouldDismissLowBatteryWarning_dismissWhenPlugged() {          mPowerUI.start();          when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml index 754ba722d081..b08924b8adb6 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml @@ -16,7 +16,7 @@    -->  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <string name="display_cutout_emulation_overlay">Corner display cutout</string> +    <string name="display_cutout_emulation_overlay">Corner cutout</string>  </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml index 68c2dcbbe3f6..0a106fa0c08f 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml @@ -16,7 +16,7 @@    -->  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <string name="display_cutout_emulation_overlay">Double display cutout</string> +    <string name="display_cutout_emulation_overlay">Double cutout</string>  </resources> diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml index 49896773ac55..0bf83306f875 100644 --- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml @@ -18,7 +18,7 @@  -->  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <string name="display_cutout_emulation_overlay">Narrow display cutout</string> +    <string name="display_cutout_emulation_overlay">Narrow cutout</string>  </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml index 6dcbbd923601..bcc7c9756a6e 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml @@ -16,7 +16,7 @@    -->  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <string name="display_cutout_emulation_overlay">Tall display cutout</string> +    <string name="display_cutout_emulation_overlay">Tall cutout</string>  </resources> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml index f4b9f7ea7c37..0fcbdebbd345 100644 --- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml @@ -16,7 +16,7 @@    -->  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> -    <string name="display_cutout_emulation_overlay">Wide display cutout</string> +    <string name="display_cutout_emulation_overlay">Wide cutout</string>  </resources> diff --git a/proto/src/gnss.proto b/proto/src/gnss.proto index 016839232255..1509fc00fb1d 100644 --- a/proto/src/gnss.proto +++ b/proto/src/gnss.proto @@ -45,6 +45,9 @@ message GnssLog {    // Power metrics    optional PowerMetrics power_metrics = 12; + +  // Hardware revision (EVT, DVT, PVT etc.) +  optional string hardware_revision = 13;  }  // Power metrics diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 03ab60c33f51..b990175fd616 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -941,9 +941,10 @@ message MetricsEvent {      // OS: 6.0      NOTIFICATION_ZEN_MODE_EVENT_RULE = 146; -    // ACTION: App notification settings > Block Notifications +    // ACTION: App notification settings > Block Notifications or long press on +    // notification blocks.      // CATEGORY: SETTINGS -    // OS: 6.0 +    // OS: 9.0      ACTION_BAN_APP_NOTES = 147;      // ACTION: Notification shade > Dismiss all button @@ -6129,6 +6130,305 @@ message MetricsEvent {      // CATEGORY: NOTIFICATION      NOTIFICATION_INTERRUPTION = 1501; +    // OPEN: Settings +    // CATEGORY: SETTINGS +    // OS: Q +    SETTINGS_HOMEPAGE = 1502; + +    // OPEN: Settings > Create shortcut(widget) +    // CATEGORY: SETTINGS +    // OS: Q +    SETTINGS_CREATE_SHORTCUT = 1503; + +    // ACTION: Authenticate using fingerprint +    // CATEGORY: SETTINGS +    // OS: Q +    ACTION_FACE_AUTH = 1504; + +    // ACTION: Add fingerprint > Enroll fingerprint +    // CATEGORY: SETTINGS +    // OS: Q +    ACTION_FACE_ENROLL = 1505; + +    // OPEN: Face Enroll introduction +    // CATEGORY: SETTINGS +    // OS: Q +    FACE_ENROLL_INTRO = 1506; + +    // OPEN: Face Enroll introduction +    // CATEGORY: SETTINGS +    // OS: Q +    FACE_ENROLL_ENROLLING = 1507; + +    // OPEN: Face Enroll introduction +    // CATEGORY: SETTINGS +    // OS: Q +    FACE_ENROLL_FINISHED = 1508; + +    // OPEN: Face Enroll sidecar +    // CATEGORY: SETTINGS +    // OS: Q +    FACE_ENROLL_SIDECAR = 1509; + +    // OPEN: Settings > Add face > Error dialog +    // OS: Q +    DIALOG_FACE_ERROR = 1510; + +    // OPEN: Settings > Security > Face +    // CATEGORY: SETTINGS +    // OS: Q +    FACE = 1511; + +    // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog +    // CATEGORY: SETTINGS +    // OS: Q +    DIALOG_ACCESSIBILITY_HEARINGAID = 1512; + +    // ACTION: Activity start +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    ACTION_ACTIVITY_START = 1513; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Calling UID +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_CALLING_UID = 1514; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Calling package name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_CALLING_PACKAGE_NAME = 1515; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Calling UID proc state +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_CALLING_UID_PROC_STATE = 1516; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Calling UID has any visible window +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1517; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Real calling UID +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_REAL_CALLING_UID = 1518; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Real calling UID proc state +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_REAL_CALLING_UID_PROC_STATE = 1519; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Real calling UID has any visible window +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW = 1520; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target UID +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_UID = 1521; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target UID package name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_PACKAGE_NAME = 1522; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target UID proc state +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_UID_PROC_STATE = 1523; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target UID has any visible window +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW = 1524; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target doze whitelist tag +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_WHITELIST_TAG = 1525; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Target short component name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_TARGET_SHORT_COMPONENT_NAME = 1526; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Coming from pending intent +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_COMING_FROM_PENDING_INTENT = 1527; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Intent action +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_INTENT_ACTION = 1528; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record process name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_PROCESS_NAME = 1529; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record current proc state +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_CUR_PROC_STATE = 1530; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record has client activities +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES = 1531; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record has foreground services +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES = 1532; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record has foreground activities +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES = 1533; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record has top UI +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_HAS_TOP_UI = 1534; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record has overlay UI +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_HAS_OVERLAY_UI = 1535; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Caller app process record pending UI clean +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_PENDING_UI_CLEAN = 1536; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Millis since caller app's process record last interaction event +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT = 1537; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Millis since caller app's process record fg interaction +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION = 1538; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Millis since caller app's process record last became unimportant +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT = 1539; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record launch mode +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_LAUNCH_MODE = 1540; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record target activity +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY = 1541; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record flags +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_FLAGS = 1542; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record real activity +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_REAL_ACTIVITY = 1543; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record short component name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME = 1544; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record process name +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_PROCESS_NAME = 1545; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record is fullscreen +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_IS_FULLSCREEN = 1546; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record is no display +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY = 1547; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Millis since activity was last visible +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE = 1548; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record's resultTo packageName +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME = 1549; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record's resultTo shortComponentName +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME = 1550; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record is visible +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_IS_VISIBLE = 1551; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Activity record is visible ignoring keyguard +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD = 1552; + +    // Tagged data for ACTION_ACTIVITY_START. +    // FIELD: Millis since activity's last launch +    // CATEGORY: OTHER +    // OS: Q (will also ship in PQ1A) +    FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH = 1553; +      // OPEN: Emergency dialer opened      // CLOSE: Emergency dialer closed      //  SUBTYPE: The entry type that user opened emergency dialer diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index 72f11e0a63c1..b29c992120d4 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -457,6 +457,11 @@ message WifiLog {    // Identifier for experimental scoring parameter settings.    optional string score_experiment_id = 117; +  // Histogram of the EAP method type of all installed Passpoint profiles +  repeated PasspointProfileTypeCount installed_passpoint_profile_type = 123; + +  // Hardware revision (EVT, DVT, PVT etc.) +  optional string hardware_revision = 124;  }  // Information that gets logged for every WiFi connection. @@ -1503,3 +1508,31 @@ message WifiRttLog {      optional int32 count = 2;    }  } + +message PasspointProfileTypeCount { +  enum EapMethod { +    // Unknown Type +    TYPE_UNKNOWN = 0; + +    // EAP_TLS (13) +    TYPE_EAP_TLS = 1; + +    // EAP_TTLS (21) +    TYPE_EAP_TTLS = 2; + +    // EAP_SIM (18) +    TYPE_EAP_SIM = 3; + +    // EAP_AKA (23) +    TYPE_EAP_AKA = 4; + +    // EAP_AKA_PRIME (50) +    TYPE_EAP_AKA_PRIME = 5; +  } + +  // Eap method type set in Passpoint profile +  optional EapMethod eap_method_type = 1; + +  // Num of installed Passpoint profile with same eap method +  optional int32 count = 2; +} diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java index c9c7adc45697..f69b6387a605 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java @@ -48,11 +48,6 @@ public class AppWidgetService extends SystemService {      }      @Override -    public void onUnlockUser(int userHandle) { -        FgThread.getHandler().post(() -> mImpl.onUserUnlocked(userHandle)); -    } - -    @Override      public void onStopUser(int userHandle) {          mImpl.onUserStopped(userHandle);      } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index db8ad12cfdf8..b71d7a726b28 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -19,7 +19,6 @@ package com.android.server.appwidget;  import static android.content.Context.KEYGUARD_SERVICE;  import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;  import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -  import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;  import android.annotation.UserIdInt; @@ -2697,7 +2696,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku          }      } -    void onUserUnlocked(int userId) { +    /** +     * This does not use the usual onUserUnlocked() listener mechanism because it is +     * invoked at a choreographed point in the middle of the user unlock sequence, +     * before the boot-completed broadcast is issued and the listeners notified. +     */ +    void handleUserUnlocked(int userId) {          if (isProfileWithLockedParent(userId)) {              return;          } @@ -2734,7 +2738,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku                  }              }          } -        Slog.i(TAG, "Async processing of onUserUnlocked u" + userId + " took " +        Slog.i(TAG, "Processing of handleUserUnlocked u" + userId + " took "                  + (SystemClock.elapsedRealtime() - time) + " ms");      } @@ -4801,5 +4805,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku                  return widgetPackages;              }          } + +        @Override +        public void unlockUser(int userId) { +            handleUserUnlocked(userId); +        } +      }  } diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index dc84498353ea..58823036212d 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -81,6 +81,13 @@ final class SaveUi {          void onDestroy();      } +    /** +     * Wrapper that guarantees that only one callback is triggered by ignoring further calls after +     * it's destroyed. +     * +     * <p>It's needed becase {@link #onCancel(IntentSender)} is always called when the Save UI +     * dialog is dismissed. +     */      private class OneTimeListener implements OnSaveListener {          private final OnSaveListener mRealListener; @@ -96,7 +103,6 @@ final class SaveUi {              if (mDone) {                  return;              } -            mDone = true;              mRealListener.onSave();          } @@ -106,7 +112,6 @@ final class SaveUi {              if (mDone) {                  return;              } -            mDone = true;              mRealListener.onCancel(listener);          } diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 5c14459da566..50f15ca0739f 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -624,7 +624,7 @@ public final class BatteryService extends SystemService {              // them will get the new sequence number at that point.  (See for example how testing              // of JobScheduler's BatteryController works.)              sendBatteryChangedIntentLocked(); -            if (mLastBatteryLevel != mHealthInfo.batteryLevel) { +            if (mLastBatteryLevel != mHealthInfo.batteryLevel || mLastPlugType != mPlugType) {                  sendBatteryLevelChangedIntentLocked();              } diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index f5b29e9b76b8..0deaee7f7878 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -43,6 +43,7 @@ import android.os.Looper;  import android.os.Message;  import android.os.RemoteException;  import android.os.UserHandle; +import android.os.UserManager;  import android.provider.MediaStore;  import android.provider.Settings;  import android.system.ErrnoException; @@ -69,6 +70,7 @@ import java.io.IOException;  import java.io.PrintWriter;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy; +import java.util.List;  import java.util.ArrayList;  import java.util.zip.ZipFile; @@ -103,6 +105,7 @@ public final class PinnerService extends SystemService {      private final Context mContext;      private final ActivityManagerInternal mAmInternal;      private final IActivityManager mAm; +    private final UserManager mUserManager;      /** The list of the statically pinned files. */      @GuardedBy("this") @@ -164,6 +167,8 @@ public final class PinnerService extends SystemService {          mAmInternal = LocalServices.getService(ActivityManagerInternal.class);          mAm = ActivityManager.getService(); +        mUserManager = mContext.getSystemService(UserManager.class); +          IntentFilter filter = new IntentFilter();          filter.addAction(Intent.ACTION_PACKAGE_REPLACED);          filter.addDataScheme("package"); @@ -194,12 +199,16 @@ public final class PinnerService extends SystemService {       */      @Override      public void onSwitchUser(int userHandle) { -        sendPinAppsMessage(userHandle); +        if (!mUserManager.isManagedProfile(userHandle)) { +            sendPinAppsMessage(userHandle); +        }      }      @Override      public void onUnlockUser(int userHandle) { -        sendPinAppsMessage(userHandle); +        if (!mUserManager.isManagedProfile(userHandle)) { +            sendPinAppsMessage(userHandle); +        }      }      /** @@ -345,31 +354,76 @@ public final class PinnerService extends SystemService {      }      private ApplicationInfo getCameraInfo(int userHandle) { -        //  find the camera via an intent -        //  use INTENT_ACTION_STILL_IMAGE_CAMERA instead of _SECURE.  On a -        //  device without a fbe enabled, the _SECURE intent will never get set.          Intent cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); -        return getApplicationInfoForIntent(cameraIntent, userHandle); +        ApplicationInfo info = getApplicationInfoForIntent(cameraIntent, userHandle, +            false /* defaultToSystemApp */); + +        // If the STILL_IMAGE_CAMERA intent doesn't resolve, try the _SECURE intent. +        // We don't use _SECURE first because it will never get set on a device +        // without File-based Encryption. But if the user has only set the intent +        // before unlocking their device, we may still be able to identify their +        // preference using this intent. +        if (info == null) { +            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); +            info = getApplicationInfoForIntent(cameraIntent, userHandle, +                false /* defaultToSystemApp */); +        } + +        // If the _SECURE intent doesn't resolve, try the original intent but request +        // the system app for camera if there was more than one result. +        if (info == null) { +            cameraIntent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); +            info = getApplicationInfoForIntent(cameraIntent, userHandle, +                true /* defaultToSystemApp */); +        } +        return info;      }      private ApplicationInfo getHomeInfo(int userHandle) {          Intent intent = mAmInternal.getHomeIntent(); -        return getApplicationInfoForIntent(intent, userHandle); +        return getApplicationInfoForIntent(intent, userHandle, false);      } -    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle) { +    private ApplicationInfo getApplicationInfoForIntent(Intent intent, int userHandle, +            boolean defaultToSystemApp) {          if (intent == null) {              return null;          } -        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(intent, + +        ResolveInfo resolveInfo = mContext.getPackageManager().resolveActivityAsUser(intent,                  MATCH_FLAGS, userHandle); -        if (info == null) { + +        // If this intent can resolve to only one app, choose that one. +        // Otherwise, if we've requested to default to the system app, return it; +        // if we have not requested that default, return null if there's more than one option. +        // If there's more than one system app, return null since we don't know which to pick. +        if (resolveInfo == null) {              return null;          } -        if (isResolverActivity(info.activityInfo)) { -            return null; + +        if (!isResolverActivity(resolveInfo.activityInfo)) { +            return resolveInfo.activityInfo.applicationInfo;          } -        return info.activityInfo.applicationInfo; + +        if (defaultToSystemApp) { +            List<ResolveInfo> infoList = mContext.getPackageManager() +                .queryIntentActivitiesAsUser(intent, MATCH_FLAGS, userHandle); +            ApplicationInfo systemAppInfo = null; +            for (ResolveInfo info : infoList) { +                if ((info.activityInfo.applicationInfo.flags +                      & ApplicationInfo.FLAG_SYSTEM) != 0) { +                    if (systemAppInfo == null) { +                        systemAppInfo = info.activityInfo.applicationInfo; +                    } else { +                        // If there's more than one system app, return null due to ambiguity. +                        return null; +                    } +                } +            } +            return systemAppInfo; +        } + +        return null;      }      private void sendPinAppsMessage(int userHandle) { diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 6550d06b8a12..9bf72fb86cd6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -207,6 +207,10 @@ final class ActivityManagerConstants extends ContentObserver {      // Indicates if the processes need to be started asynchronously.      public boolean FLAG_PROCESS_START_ASYNC = DEFAULT_PROCESS_START_ASYNC; +    // Indicates whether the activity starts logging is enabled. +    // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED +    boolean mFlagActivityStartsLoggingEnabled; +      private final ActivityManagerService mService;      private ContentResolver mResolver;      private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -235,6 +239,12 @@ final class ActivityManagerConstants extends ContentObserver {      // memory trimming.      public int CUR_TRIM_CACHED_PROCESSES; +    private static final Uri ACTIVITY_MANAGER_CONSTANTS_URI = Settings.Global.getUriFor( +                Settings.Global.ACTIVITY_MANAGER_CONSTANTS); + +    private static final Uri ACTIVITY_STARTS_LOGGING_ENABLED_URI = Settings.Global.getUriFor( +                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED); +      public ActivityManagerConstants(ActivityManagerService service, Handler handler) {          super(handler);          mService = service; @@ -243,9 +253,10 @@ final class ActivityManagerConstants extends ContentObserver {      public void start(ContentResolver resolver) {          mResolver = resolver; -        mResolver.registerContentObserver(Settings.Global.getUriFor( -                Settings.Global.ACTIVITY_MANAGER_CONSTANTS), false, this); +        mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this); +        mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);          updateConstants(); +        updateActivityStartsLoggingEnabled();      }      public void setOverrideMaxCachedProcesses(int value) { @@ -263,7 +274,12 @@ final class ActivityManagerConstants extends ContentObserver {      @Override      public void onChange(boolean selfChange, Uri uri) { -        updateConstants(); +        if (uri == null) return; +        if (ACTIVITY_MANAGER_CONSTANTS_URI.equals(uri)) { +            updateConstants(); +        } else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) { +            updateActivityStartsLoggingEnabled(); +        }      }      private void updateConstants() { @@ -337,6 +353,11 @@ final class ActivityManagerConstants extends ContentObserver {          }      } +    private void updateActivityStartsLoggingEnabled() { +        mFlagActivityStartsLoggingEnabled = Settings.Global.getInt(mResolver, +                Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 0) == 1; +    } +      private void updateMaxCachedProcesses() {          CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0                  ? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1dec3bf66ba6..904d8f058bb5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5591,7 +5591,7 @@ public class ActivityManagerService extends IActivityManager.Stub          // TODO: Switch to user app stacks here.          int ret = mActivityStartController.startActivities(caller, -1, callingPackage,                  intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, -                reason); +                reason, null /* originatingPendingIntent */);          return ret;      } @@ -9498,10 +9498,17 @@ public class ActivityManagerService extends IActivityManager.Stub              }          } -        // If we're extending a persistable grant, then we always need to create -        // the grant data structure so that take/release APIs work +        // Figure out the value returned when access is allowed +        final int allowedResult;          if ((modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) { -            return targetUid; +            // If we're extending a persistable grant, then we need to return +            // "targetUid" so that we always create a grant data structure to +            // support take/release APIs +            allowedResult = targetUid; +        } else { +            // Otherwise, we can return "-1" to indicate that no grant data +            // structures need to be created +            allowedResult = -1;          }          if (targetUid >= 0) { @@ -9510,7 +9517,7 @@ public class ActivityManagerService extends IActivityManager.Stub                  // No need to grant the target this permission.                  if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION,                          "Target " + targetPkg + " already has full permission to " + grantUri); -                return -1; +                return allowedResult;              }          } else {              // First...  there is no target package, so can anyone access it? @@ -9545,7 +9552,7 @@ public class ActivityManagerService extends IActivityManager.Stub                  }              }              if (allowed) { -                return -1; +                return allowedResult;              }          } @@ -10927,6 +10934,20 @@ public class ActivityManagerService extends IActivityManager.Stub          }      } +    /** +     * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on +     * the whitelist +     */ +    String getPendingTempWhitelistTagForUidLocked(int uid) { +        final PendingTempWhitelist ptw = mPendingTempWhitelist.get(uid); +        return ptw != null ? ptw.tag : null; +    } + +    @VisibleForTesting +    boolean isActivityStartsLoggingEnabled() { +        return mConstants.mFlagActivityStartsLoggingEnabled; +    } +      @Override      public void moveStackToDisplay(int stackId, int displayId) {          enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()"); @@ -26379,7 +26400,7 @@ public class ActivityManagerService extends IActivityManager.Stub                          packageUid, packageName,                          intents, resolvedTypes, null /* resultTo */,                          SafeActivityOptions.fromBundle(bOptions), userId, -                        false /* validateIncomingUser */); +                        false /* validateIncomingUser */, null /* originatingPendingIntent */);              }          } @@ -26718,6 +26739,18 @@ public class ActivityManagerService extends IActivityManager.Stub                  return ActivityManagerService.this.getHomeIntent();              }          } + +        @Override +        public void notifyDefaultDisplaySizeChanged() { +            synchronized (ActivityManagerService.this) { +                if (mSystemServiceManager.isBootCompleted() && mHomeProcess != null) { + +                    // TODO: Ugly hack to unblock the release +                    Slog.i(TAG, "Killing home process because of display size change"); +                    removeProcessLocked(mHomeProcess, false, true, "kill home screen size"); +                } +            } +        }      }      /** diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index dc9a5adb5a0c..093bd87813d5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2844,6 +2844,7 @@ final class ActivityManagerShellCommand extends ShellCommand {              pw.println("  --checkin: output checkin format, resetting data.");              pw.println("  --C: output checkin format, not resetting data.");              pw.println("  --proto: output dump in protocol buffer format."); +            pw.println("  --autofill: dump just the autofill-related state of an activity");          } else {              pw.println("Activity manager (activity) commands:");              pw.println("  help"); diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 47d0423550c4..9ffa6627836f 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -2,6 +2,7 @@ package com.android.server.am;  import static android.app.ActivityManager.START_SUCCESS;  import static android.app.ActivityManager.START_TASK_TO_FRONT; +import static android.app.ActivityManager.processStateAmToProto;  import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;  import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;  import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -9,6 +10,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;  import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;  import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;  import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ACTIVITY_START;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_BIND_APPLICATION_DELAY_MS;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME; @@ -21,8 +23,48 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TR  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_FLAGS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_FULLSCREEN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_LAUNCH_MODE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_PROCESS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_REAL_ACTIVITY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_PACKAGE_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CALLING_UID_PROC_STATE;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_COMING_FROM_PENDING_INTENT;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INTENT_ACTION; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_CUR_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_OVERLAY_UI; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_HAS_TOP_UI; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PENDING_UI_CLEAN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_PROCESS_RECORD_PROCESS_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_PACKAGE_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_SHORT_COMPONENT_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_UID_PROC_STATE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_TARGET_WHITELIST_TAG;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;  import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH; @@ -37,6 +79,7 @@ import static com.android.server.am.MemoryStatUtil.MemoryStat;  import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;  import android.content.Context; +import android.content.Intent;  import android.content.pm.ApplicationInfo;  import android.content.pm.dex.ArtManagerInternal;  import android.content.pm.dex.PackageOptimizationInfo; @@ -622,6 +665,95 @@ class ActivityMetricsLogger {                  startupTimeMs);      } +    void logActivityStart(Intent intent, ProcessRecord callerApp, ActivityRecord r, +            int callingUid, String callingPackage, int callingUidProcState, +            boolean callingUidHasAnyVisibleWindow, +            int realCallingUid, int realCallingUidProcState, +            boolean realCallingUidHasAnyVisibleWindow, +            int targetUid, String targetPackage, int targetUidProcState, +            boolean targetUidHasAnyVisibleWindow, String targetWhitelistTag, +            boolean comingFromPendingIntent) { + +        final long nowElapsed = SystemClock.elapsedRealtime(); +        final long nowUptime = SystemClock.uptimeMillis(); +        final LogMaker builder = new LogMaker(ACTION_ACTIVITY_START); +        builder.setTimestamp(System.currentTimeMillis()); +        builder.addTaggedData(FIELD_CALLING_UID, callingUid); +        builder.addTaggedData(FIELD_CALLING_PACKAGE_NAME, callingPackage); +        builder.addTaggedData(FIELD_CALLING_UID_PROC_STATE, +                processStateAmToProto(callingUidProcState)); +        builder.addTaggedData(FIELD_CALLING_UID_HAS_ANY_VISIBLE_WINDOW, +                callingUidHasAnyVisibleWindow ? 1 : 0); +        builder.addTaggedData(FIELD_REAL_CALLING_UID, realCallingUid); +        builder.addTaggedData(FIELD_REAL_CALLING_UID_PROC_STATE, +                processStateAmToProto(realCallingUidProcState)); +        builder.addTaggedData(FIELD_REAL_CALLING_UID_HAS_ANY_VISIBLE_WINDOW, +                realCallingUidHasAnyVisibleWindow ? 1 : 0); +        builder.addTaggedData(FIELD_TARGET_UID, targetUid); +        builder.addTaggedData(FIELD_TARGET_PACKAGE_NAME, targetPackage); +        builder.addTaggedData(FIELD_TARGET_UID_PROC_STATE, +                processStateAmToProto(targetUidProcState)); +        builder.addTaggedData(FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW, +                targetUidHasAnyVisibleWindow ? 1 : 0); +        builder.addTaggedData(FIELD_TARGET_WHITELIST_TAG, targetWhitelistTag); +        builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName); +        builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0); +        builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction()); +        if (callerApp != null) { +            builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.processName); +            builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE, +                    processStateAmToProto(callerApp.curProcState)); +            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_CLIENT_ACTIVITIES, +                    callerApp.hasClientActivities ? 1 : 0); +            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_SERVICES, +                    callerApp.hasForegroundServices() ? 1 : 0); +            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_FOREGROUND_ACTIVITIES, +                    callerApp.foregroundActivities ? 1 : 0); +            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_TOP_UI, callerApp.hasTopUi ? 1 : 0); +            builder.addTaggedData(FIELD_PROCESS_RECORD_HAS_OVERLAY_UI, +                    callerApp.hasOverlayUi ? 1 : 0); +            builder.addTaggedData(FIELD_PROCESS_RECORD_PENDING_UI_CLEAN, +                    callerApp.pendingUiClean ? 1 : 0); +            if (callerApp.interactionEventTime != 0) { +                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_LAST_INTERACTION_EVENT, +                        (nowElapsed - callerApp.interactionEventTime)); +            } +            if (callerApp.fgInteractionTime != 0) { +                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_FG_INTERACTION, +                        (nowElapsed - callerApp.fgInteractionTime)); +            } +            if (callerApp.whenUnimportant != 0) { +                builder.addTaggedData(FIELD_PROCESS_RECORD_MILLIS_SINCE_UNIMPORTANT, +                        (nowUptime - callerApp.whenUnimportant)); +            } +        } +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY, r.realActivity.toShortString()); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0); +        if (r.lastVisibleTime != 0) { +            builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE, +                    (nowUptime - r.lastVisibleTime)); +        } +        if (r.resultTo != null) { +            builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME, r.resultTo.packageName); +            builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME, +                    r.resultTo.shortComponentName); +        } +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0); +        builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD, +                r.visibleIgnoringKeyguard ? 1 : 0); +        if (r.lastLaunchTime != 0) { +            builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH, +                    (nowUptime - r.lastLaunchTime)); +        } +        mMetricsLogger.write(builder); +    } +      private int getTransitionType(WindowingModeTransitionInfo info) {          if (info.currentTransitionProcessRunning) {              if (info.startResult == START_SUCCESS) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 75f27231c976..60f79f720242 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -694,9 +694,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo          final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;          if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {              // Picture-in-picture mode changes also trigger a multi-window mode change as well, so -            // update that here in order +            // update that here in order. Set the last reported MW state to the same as the PiP +            // state since we haven't yet actually resized the task (these callbacks need to +            // preceed the configuration change from the resiez. +            // TODO(110009072): Once we move these callbacks to the client, remove all logic related +            // to forcing the update of the picture-in-picture mode as a part of the PiP animation.              mLastReportedPictureInPictureMode = inPictureInPictureMode; -            mLastReportedMultiWindowMode = inMultiWindowMode(); +            mLastReportedMultiWindowMode = inPictureInPictureMode;              final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(                      targetStackBounds, null);              schedulePictureInPictureModeChanged(newConfig); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index c520101d3ff4..2ae056fe18a5 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -4853,7 +4853,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D              return mService.getActivityStartController().startActivityInPackage(                      task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,                      null, 0, 0, options, userId, task, "startActivityFromRecents", -                    false /* validateIncomingUser */); +                    false /* validateIncomingUser */, null /* originatingPendingIntent */);          } finally {              if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && task != null) {                  // If we are launching the task in the docked stack, put it into resizing mode so diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java index a7c32009a4c4..edcf6e7bd516 100644 --- a/services/core/java/com/android/server/am/ActivityStartController.java +++ b/services/core/java/com/android/server/am/ActivityStartController.java @@ -248,7 +248,8 @@ public class ActivityStartController {      final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,              String callingPackage, Intent intent, String resolvedType, IBinder resultTo,              String resultWho, int requestCode, int startFlags, SafeActivityOptions options, -            int userId, TaskRecord inTask, String reason, boolean validateIncomingUser) { +            int userId, TaskRecord inTask, String reason, boolean validateIncomingUser, +            PendingIntentRecord originatingPendingIntent) {          userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid,                  reason); @@ -267,6 +268,7 @@ public class ActivityStartController {                  .setActivityOptions(options)                  .setMayWait(userId)                  .setInTask(inTask) +                .setOriginatingPendingIntent(originatingPendingIntent)                  .execute();      } @@ -278,10 +280,12 @@ public class ActivityStartController {       * @param intents Intents to start.       * @param userId Start the intents on this user.       * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. +     * @param originatingPendingIntent PendingIntentRecord that originated this activity start or +     *        null if not originated by PendingIntent       */      final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,              String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, -            boolean validateIncomingUser) { +            boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent) {          final String reason = "startActivityInPackage"; @@ -290,12 +294,12 @@ public class ActivityStartController {          // TODO: Switch to user app stacks here.          return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options, -                userId, reason); +                userId, reason, originatingPendingIntent);      }      int startActivities(IApplicationThread caller, int callingUid, String callingPackage,              Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, -            int userId, String reason) { +            int userId, String reason, PendingIntentRecord originatingPendingIntent) {          if (intents == null) {              throw new NullPointerException("intents is null");          } @@ -374,6 +378,7 @@ public class ActivityStartController {                              // Top activity decides on animation being run, so we allow only for the                              // top one as otherwise an activity below might consume it.                              .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/) +                            .setOriginatingPendingIntent(originatingPendingIntent)                              .execute();                      if (res < 0) { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 73e3d33073fc..00ba3a61d1d6 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -99,6 +99,7 @@ import android.os.Bundle;  import android.os.IBinder;  import android.os.RemoteException;  import android.os.SystemClock; +import android.os.Trace;  import android.os.UserHandle;  import android.os.UserManager;  import android.service.voice.IVoiceInteractionSession; @@ -313,6 +314,7 @@ class ActivityStarter {          int userId;          WaitResult waitResult;          int filterCallingUid; +        PendingIntentRecord originatingPendingIntent;          /**           * If set to {@code true}, allows this activity start to look into @@ -369,6 +371,7 @@ class ActivityStarter {              avoidMoveToFront = false;              allowPendingRemoteAnimationRegistryLookup = true;              filterCallingUid = UserHandle.USER_NULL; +            originatingPendingIntent = null;          }          /** @@ -407,6 +410,7 @@ class ActivityStarter {              allowPendingRemoteAnimationRegistryLookup                      = request.allowPendingRemoteAnimationRegistryLookup;              filterCallingUid = request.filterCallingUid; +            originatingPendingIntent = request.originatingPendingIntent;          }      } @@ -490,7 +494,8 @@ class ActivityStarter {                          mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,                          mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,                          mRequest.inTask, mRequest.reason, -                        mRequest.allowPendingRemoteAnimationRegistryLookup); +                        mRequest.allowPendingRemoteAnimationRegistryLookup, +                        mRequest.originatingPendingIntent);              } else {                  return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,                          mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo, @@ -500,7 +505,8 @@ class ActivityStarter {                          mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,                          mRequest.ignoreTargetSecurity, mRequest.componentSpecified,                          mRequest.outActivity, mRequest.inTask, mRequest.reason, -                        mRequest.allowPendingRemoteAnimationRegistryLookup); +                        mRequest.allowPendingRemoteAnimationRegistryLookup, +                        mRequest.originatingPendingIntent);              }          } finally {              onExecutionComplete(); @@ -532,7 +538,8 @@ class ActivityStarter {              String callingPackage, int realCallingPid, int realCallingUid, int startFlags,              SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,              ActivityRecord[] outActivity, TaskRecord inTask, String reason, -            boolean allowPendingRemoteAnimationRegistryLookup) { +            boolean allowPendingRemoteAnimationRegistryLookup, +            PendingIntentRecord originatingPendingIntent) {          if (TextUtils.isEmpty(reason)) {              throw new IllegalArgumentException("Need to specify a reason."); @@ -545,7 +552,7 @@ class ActivityStarter {                  aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,                  callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,                  options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, -                inTask, allowPendingRemoteAnimationRegistryLookup); +                inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);          if (outActivity != null) {              // mLastStartActivityRecord[0] is set in the call to startActivity above. @@ -575,7 +582,8 @@ class ActivityStarter {              String callingPackage, int realCallingPid, int realCallingUid, int startFlags,              SafeActivityOptions options,              boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, -            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) { +            TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup, +            PendingIntentRecord originatingPendingIntent) {          int err = ActivityManager.START_SUCCESS;          // Pull the optional Ephemeral Installer-only bundle out of the options early.          final Bundle verificationBundle @@ -865,10 +873,58 @@ class ActivityStarter {          mController.doPendingActivityLaunches(false); +        maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp, r, +                originatingPendingIntent); +          return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,                  true /* doResume */, checkedOptions, inTask, outActivity);      } +    private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid, +            Intent intent, ProcessRecord callerApp, ActivityRecord r, +            PendingIntentRecord originatingPendingIntent) { +        boolean callerAppHasForegroundActivity = (callerApp != null) +                ? callerApp.foregroundActivities +                : false; +        if (!mService.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity +                || r == null) { +            // skip logging in this case +            return; +        } + +        try { +            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart"); +            final int callingUidProcState = mService.getUidStateLocked(callingUid); +            final boolean callingUidHasAnyVisibleWindow = +                    mService.mWindowManager.isAnyWindowVisibleForUid(callingUid); +            final int realCallingUidProcState = (callingUid == realCallingUid) +                    ? callingUidProcState +                    : mService.getUidStateLocked(realCallingUid); +            final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid) +                    ? callingUidHasAnyVisibleWindow +                    : mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid); +            final String targetPackage = r.packageName; +            final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1; +            final int targetUidProcState = mService.getUidStateLocked(targetUid); +            final boolean targetUidHasAnyVisibleWindow = (targetUid != -1) +                    ? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid) +                    : false; +            final String targetWhitelistTag = (targetUid != -1) +                    ? mService.getPendingTempWhitelistTagForUidLocked(targetUid) +                    : null; + +            mSupervisor.getActivityMetricsLogger().logActivityStart(intent, callerApp, r, +                    callingUid, callingPackage, callingUidProcState, +                    callingUidHasAnyVisibleWindow, +                    realCallingUid, realCallingUidProcState, +                    realCallingUidHasAnyVisibleWindow, +                    targetUid, targetPackage, targetUidProcState, +                    targetUidHasAnyVisibleWindow, targetWhitelistTag, +                    (originatingPendingIntent != null)); +        } finally { +            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); +        } +    }      /**       * Creates a launch intent for the given auxiliary resolution data. @@ -949,7 +1005,8 @@ class ActivityStarter {              ProfilerInfo profilerInfo, WaitResult outResult,              Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,              int userId, TaskRecord inTask, String reason, -            boolean allowPendingRemoteAnimationRegistryLookup) { +            boolean allowPendingRemoteAnimationRegistryLookup, +            PendingIntentRecord originatingPendingIntent) {          // Refuse possible leaked file descriptors          if (intent != null && intent.hasFileDescriptors()) {              throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -1100,7 +1157,7 @@ class ActivityStarter {                      voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,                      callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,                      ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason, -                    allowPendingRemoteAnimationRegistryLookup); +                    allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent);              Binder.restoreCallingIdentity(origId); @@ -2625,6 +2682,11 @@ class ActivityStarter {          return this;      } +    ActivityStarter setOriginatingPendingIntent(PendingIntentRecord originatingPendingIntent) { +        mRequest.originatingPendingIntent = originatingPendingIntent; +        return this; +    } +      void dump(PrintWriter pw, String prefix) {          prefix = prefix + "  ";          pw.print(prefix); diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index a6dafbb1db36..f0e2876b4761 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -484,7 +484,8 @@ class AppErrors {                                      task.intent, null, null, null, 0, 0,                                      new SafeActivityOptions(ActivityOptions.makeBasic()),                                      task.userId, null, -                                    "AppErrors", false /*validateIncomingUser*/); +                                    "AppErrors", false /*validateIncomingUser*/, +                                    null /* originatingPendingIntent */);                          }                      }                  } diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index e0aa2a261b3c..4e00304a9da6 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -307,7 +307,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {                              } else if (finalIntent.getComponent() != null) {                                  finalIntent.getComponent().appendShortString(tag);                              } else if (finalIntent.getData() != null) { -                                tag.append(finalIntent.getData()); +                                tag.append(finalIntent.getData().toSafeString());                              }                              owner.tempWhitelistForPendingIntentLocked(callingPid,                                      callingUid, uid, duration, tag.toString()); @@ -346,13 +346,15 @@ final class PendingIntentRecord extends IIntentSender.Stub {                                  res = owner.getActivityStartController().startActivitiesInPackage(                                          uid, key.packageName, allIntents, allResolvedTypes,                                          resultTo, mergedOptions, userId, -                                        false /* validateIncomingUser */); +                                        false /* validateIncomingUser */, +                                        this /* originatingPendingIntent */);                              } else {                                  res = owner.getActivityStartController().startActivityInPackage(uid,                                          callingPid, callingUid, key.packageName, finalIntent,                                          resolvedType, resultTo, resultWho, requestCode, 0,                                          mergedOptions, userId, null, "PendingIntentRecord", -                                        false /* validateIncomingUser */); +                                        false /* validateIncomingUser */, +                                        this /* originatingPendingIntent */);                              }                          } catch (RuntimeException e) {                              Slog.w(TAG, "Unable to send startActivity intent", e); diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index caf52e359548..28ebbb87f261 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -856,4 +856,8 @@ final class ProcessRecord {          }          return list;      } + +    boolean hasForegroundServices() { +        return foregroundServices; +    }  } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 18c095725b09..415a822e3160 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -24,7 +24,6 @@ import static android.app.ActivityManager.USER_OP_IS_CURRENT;  import static android.app.ActivityManager.USER_OP_SUCCESS;  import static android.os.Process.SHELL_UID;  import static android.os.Process.SYSTEM_UID; -  import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;  import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;  import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -48,6 +47,7 @@ import android.app.IStopUserCallback;  import android.app.IUserSwitchObserver;  import android.app.KeyguardManager;  import android.app.usage.UsageEvents; +import android.appwidget.AppWidgetManagerInternal;  import android.content.Context;  import android.content.IIntentReceiver;  import android.content.Intent; @@ -87,8 +87,8 @@ import android.util.SparseArray;  import android.util.SparseIntArray;  import android.util.TimingsTraceLog;  import android.util.proto.ProtoOutputStream; -  import android.view.Window; +  import com.android.internal.R;  import com.android.internal.annotations.GuardedBy;  import com.android.internal.annotations.VisibleForTesting; @@ -533,6 +533,9 @@ class UserController implements Handler.Callback {              }          } +        // Spin up app widgets prior to boot-complete, so they can be ready promptly +        mInjector.startUserWidgets(userId); +          Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId);          // Do not report secondary users, runtime restarts or first boot/upgrade          if (userId == UserHandle.USER_SYSTEM @@ -2173,6 +2176,13 @@ class UserController implements Handler.Callback {              }          } +        void startUserWidgets(int userId) { +            AppWidgetManagerInternal awm = LocalServices.getService(AppWidgetManagerInternal.class); +            if (awm != null) { +                awm.unlockUser(userId); +            } +        } +          void updateUserConfiguration() {              synchronized (mService) {                  mService.updateUserConfigurationLocked(); diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 349e1c8b713e..512e85192d36 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -104,6 +104,12 @@ final class DisplayDeviceInfo {      public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10;      /** +     * Flag: The display cutout of this display is masked. +     * @hide +     */ +    public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11; + +    /**       * Touch attachment: Display does not receive touch.       */      public static final int TOUCH_NONE = 0; @@ -453,6 +459,9 @@ final class DisplayDeviceInfo {          if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {              msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");          } +        if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) { +            msg.append(", FLAG_MASK_DISPLAY_CUTOUT"); +        }          return msg.toString();      }  } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index ddd8855f3199..cc5a8271eb5f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -151,6 +151,8 @@ public final class DisplayManagerService extends SystemService {      // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.      private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; +    private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top"; +      private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;      private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1; @@ -243,6 +245,15 @@ public final class DisplayManagerService extends SystemService {      // device).      private Point mStableDisplaySize = new Point(); +    // Whether the system has finished booting or not. +    private boolean mSystemReady; + +    // The top inset of the default display. +    // This gets persisted so that the boot animation knows how to transition from the display's +    // full size to the size configured by the user. Right now we only persist and animate the top +    // inset, but theoretically we could do it for all of them. +    private int mDefaultDisplayTopInset; +      // Viewports of the default display and the display that should receive touch      // input from an external source.  Used by the input system.      private final DisplayViewport mDefaultViewport = new DisplayViewport(); @@ -301,6 +312,7 @@ public final class DisplayManagerService extends SystemService {          Resources resources = mContext.getResources();          mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(                  com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); +        mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);          float[] lux = getFloatArray(resources.obtainTypedArray(                  com.android.internal.R.array.config_minimumBrightnessCurveLux));          float[] nits = getFloatArray(resources.obtainTypedArray( @@ -311,6 +323,8 @@ public final class DisplayManagerService extends SystemService {          PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);          mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();          mCurrentUserId = UserHandle.USER_SYSTEM; + +        mSystemReady = false;      }      public void setupSchedulerPolicies() { @@ -400,6 +414,10 @@ public final class DisplayManagerService extends SystemService {          synchronized (mSyncRoot) {              mSafeMode = safeMode;              mOnlyCore = onlyCore; +            mSystemReady = true; +            // Just in case the top inset changed before the system was ready. At this point, any +            // relevant configuration should be in place. +            recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));          }          mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); @@ -457,7 +475,7 @@ public final class DisplayManagerService extends SystemService {              LogicalDisplay display = mLogicalDisplays.get(displayId);              if (display != null) {                  if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { -                    sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); +                    handleLogicalDisplayChanged(displayId, display);                      scheduleTraversalLocked(false);                  }              } @@ -938,6 +956,13 @@ public final class DisplayManagerService extends SystemService {          scheduleTraversalLocked(false);      } +    private void handleLogicalDisplayChanged(int displayId, @NonNull LogicalDisplay display) { +        if (displayId == Display.DEFAULT_DISPLAY) { +            recordTopInsetLocked(display); +        } +        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); +    } +      private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {          final int count = mDisplayDevices.size();          for (int i = 0; i < count; i++) { @@ -991,6 +1016,7 @@ public final class DisplayManagerService extends SystemService {          configureColorModeLocked(display, device);          if (isDefault) {              recordStableDisplayStatsIfNeededLocked(display); +            recordTopInsetLocked(display);          }          mLogicalDisplays.put(displayId, display); @@ -1039,6 +1065,21 @@ public final class DisplayManagerService extends SystemService {          }      } +    private void recordTopInsetLocked(@Nullable LogicalDisplay d) { +        // We must only persist the inset after boot has completed, otherwise we will end up +        // overwriting the persisted value before the masking flag has been loaded from the +        // resource overlay. +        if (!mSystemReady || d == null) { +            return; +        } +        int topInset = d.getInsets().top; +        if (topInset == mDefaultDisplayTopInset) { +            return; +        } +        mDefaultDisplayTopInset = topInset; +        SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset)); +    } +      private void setStableDisplaySizeLocked(int width, int height) {          mStableDisplaySize = new Point(width, height);          try { @@ -1118,7 +1159,7 @@ public final class DisplayManagerService extends SystemService {                  sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);                  changed = true;              } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { -                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); +                handleLogicalDisplayChanged(displayId, display);                  changed = true;              }          } diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 21ae048e1d75..16d82df4dd5b 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -402,6 +402,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {                              && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {                          mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;                      } +                    if (res.getBoolean( +                            com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) { +                        mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT; +                    }                      mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,                              mInfo.width, mInfo.height);                      mInfo.type = Display.TYPE_BUILT_IN; diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 23ee56b24b19..5b7c5205ce3a 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -18,11 +18,14 @@ package com.android.server.display;  import android.graphics.Rect;  import android.hardware.display.DisplayManagerInternal; +import android.os.SystemProperties;  import android.view.Display;  import android.view.DisplayInfo;  import android.view.Surface;  import android.view.SurfaceControl; +import com.android.server.wm.utils.InsetUtils; +  import java.io.PrintWriter;  import java.util.Arrays;  import java.util.List; @@ -55,6 +58,8 @@ import java.util.Objects;   * </p>   */  final class LogicalDisplay { +    private static final String PROP_MASKING_INSET_TOP = "persist.sys.displayinset.top"; +      private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();      // The layer stack we use when the display has been blanked to prevent any @@ -251,14 +256,18 @@ final class LogicalDisplay {              if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {                  mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;              } +            Rect maskingInsets = getMaskingInsets(deviceInfo); +            int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right; +            int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom; +              mBaseDisplayInfo.type = deviceInfo.type;              mBaseDisplayInfo.address = deviceInfo.address;              mBaseDisplayInfo.name = deviceInfo.name;              mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId; -            mBaseDisplayInfo.appWidth = deviceInfo.width; -            mBaseDisplayInfo.appHeight = deviceInfo.height; -            mBaseDisplayInfo.logicalWidth = deviceInfo.width; -            mBaseDisplayInfo.logicalHeight = deviceInfo.height; +            mBaseDisplayInfo.appWidth = maskedWidth; +            mBaseDisplayInfo.appHeight = maskedHeight; +            mBaseDisplayInfo.logicalWidth = maskedWidth; +            mBaseDisplayInfo.logicalHeight = maskedHeight;              mBaseDisplayInfo.rotation = Surface.ROTATION_0;              mBaseDisplayInfo.modeId = deviceInfo.modeId;              mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId; @@ -275,13 +284,15 @@ final class LogicalDisplay {              mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;              mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;              mBaseDisplayInfo.state = deviceInfo.state; -            mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width; -            mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height; -            mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width; -            mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height; +            mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth; +            mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight; +            mBaseDisplayInfo.largestNominalAppWidth = maskedWidth; +            mBaseDisplayInfo.largestNominalAppHeight = maskedHeight;              mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;              mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName; -            mBaseDisplayInfo.displayCutout = deviceInfo.displayCutout; +            boolean maskCutout = +                    (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; +            mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;              mPrimaryDisplayDeviceInfo = deviceInfo;              mInfo = null; @@ -289,6 +300,29 @@ final class LogicalDisplay {      }      /** +     * Return the insets currently applied to the display. +     * +     * Note that the base DisplayInfo already takes these insets into account, so if you want to +     * find out the <b>true</b> size of the display, you need to add them back to the logical +     * dimensions. +     */ +    public Rect getInsets() { +        return getMaskingInsets(mPrimaryDisplayDeviceInfo); +    } + +    /** +     * Returns insets in ROTATION_0 for areas that are masked. +     */ +    private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) { +        boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; +        if (maskCutout && deviceInfo.displayCutout != null) { +            return deviceInfo.displayCutout.getSafeInsets(); +        } else { +            return new Rect(); +        } +    } + +    /**       * Applies the layer stack and transformation to the given display device       * so that it shows the contents of this logical display.       * @@ -349,6 +383,12 @@ final class LogicalDisplay {          int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;          int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height; +        Rect maskingInsets = getMaskingInsets(displayDeviceInfo); +        InsetUtils.rotateInsets(maskingInsets, orientation); +        // Don't consider the masked area as available when calculating the scaling below. +        physWidth -= maskingInsets.left + maskingInsets.right; +        physHeight -= maskingInsets.top + maskingInsets.bottom; +          // Determine whether the width or height is more constrained to be scaled.          //    physWidth / displayInfo.logicalWidth    => letter box          // or physHeight / displayInfo.logicalHeight  => pillar box @@ -375,6 +415,9 @@ final class LogicalDisplay {          mTempDisplayRect.set(displayRectLeft, displayRectTop,                  displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight); +        // Now add back the offset for the masked area. +        mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); +          mTempDisplayRect.left += mDisplayOffsetX;          mTempDisplayRect.right += mDisplayOffsetX;          mTempDisplayRect.top += mDisplayOffsetY; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 60e9eaab5721..e7459a40a9da 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -945,7 +945,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {      @Override      public long getIfaceStats(String iface, int type) { -        return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); +        // eBPF code doesn't provide per-interface TCP counters. Use xt_qtaguid for now. +        // TODO: delete getMobileTcp(Rx|Tx)Packets entirely. See b/110443385 . +        if (type == TYPE_TCP_TX_PACKETS || type == TYPE_TCP_RX_PACKETS) { +            return nativeGetIfaceStat(iface, type, false); +        } else { +            return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); +        }      }      @Override diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index c0fbfbb20b95..18f4bc768632 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -150,6 +150,7 @@ public class ConditionProviders extends ManagedServices {          try {              provider.onConnected();          } catch (RemoteException e) { +            Slog.e(TAG, "can't connect to service " + info, e);              // we tried          }          if (mCallback != null) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 1284468947c2..c6e71e53d595 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2122,6 +2122,10 @@ public class NotificationManagerService extends SystemService {              enforceSystemOrSystemUI("setNotificationsEnabledForPackage");              mRankingHelper.setEnabled(pkg, uid, enabled); +            mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES) +                    .setType(MetricsEvent.TYPE_ACTION) +                    .setPackageName(pkg) +                    .setSubtype(enabled ? 1 : 0));              // Now, cancel any outstanding notifications that are part of a just-disabled app              if (!enabled) {                  cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true, diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java index 67608753a2c3..b016fafa3d29 100644 --- a/services/core/java/com/android/server/notification/ZenLog.java +++ b/services/core/java/com/android/server/notification/ZenLog.java @@ -36,7 +36,8 @@ import java.util.List;  public class ZenLog {      private static final String TAG = "ZenLog"; -    private static final boolean DEBUG = Build.IS_DEBUGGABLE; +    // the ZenLog is *very* verbose, so be careful about setting this to true +    private static final boolean DEBUG = false;      private static final int SIZE = Build.IS_DEBUGGABLE ? 100 : 20; diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java index 63c0bafe389d..b080a73c1e42 100644 --- a/services/core/java/com/android/server/notification/ZenModeConditions.java +++ b/services/core/java/com/android/server/notification/ZenModeConditions.java @@ -19,7 +19,6 @@ package com.android.server.notification;  import android.content.ComponentName;  import android.net.Uri;  import android.service.notification.Condition; -import android.service.notification.IConditionListener;  import android.service.notification.IConditionProvider;  import android.service.notification.ZenModeConfig;  import android.service.notification.ZenModeConfig.ZenRule; @@ -27,6 +26,8 @@ import android.util.ArrayMap;  import android.util.ArraySet;  import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; +  import java.io.PrintWriter;  import java.util.Objects; @@ -36,7 +37,9 @@ public class ZenModeConditions implements ConditionProviders.Callback {      private final ZenModeHelper mHelper;      private final ConditionProviders mConditionProviders; -    private final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>(); + +    @VisibleForTesting +    protected final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>();      private boolean mFirstEvaluation = true; @@ -59,7 +62,8 @@ public class ZenModeConditions implements ConditionProviders.Callback {          pw.print(prefix); pw.print("mSubscriptions="); pw.println(mSubscriptions);      } -    public void evaluateConfig(ZenModeConfig config, boolean processSubscriptions) { +    public void evaluateConfig(ZenModeConfig config, ComponentName trigger, +            boolean processSubscriptions) {          if (config == null) return;          if (config.manualRule != null && config.manualRule.condition != null                  && !config.manualRule.isTrueOrUnknown()) { @@ -67,9 +71,9 @@ public class ZenModeConditions implements ConditionProviders.Callback {              config.manualRule = null;          }          final ArraySet<Uri> current = new ArraySet<>(); -        evaluateRule(config.manualRule, current, processSubscriptions); +        evaluateRule(config.manualRule, current, null, processSubscriptions);          for (ZenRule automaticRule : config.automaticRules.values()) { -            evaluateRule(automaticRule, current, processSubscriptions); +            evaluateRule(automaticRule, current, trigger, processSubscriptions);              updateSnoozing(automaticRule);          } @@ -102,7 +106,7 @@ public class ZenModeConditions implements ConditionProviders.Callback {      @Override      public void onServiceAdded(ComponentName component) {          if (DEBUG) Log.d(TAG, "onServiceAdded " + component); -        mHelper.setConfig(mHelper.getConfig(), "zmc.onServiceAdded"); +        mHelper.setConfig(mHelper.getConfig(), component, "zmc.onServiceAdded");      }      @Override @@ -110,17 +114,22 @@ public class ZenModeConditions implements ConditionProviders.Callback {          if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition);          ZenModeConfig config = mHelper.getConfig();          if (config == null) return; +        ComponentName trigger = null;          boolean updated = updateCondition(id, condition, config.manualRule);          for (ZenRule automaticRule : config.automaticRules.values()) {              updated |= updateCondition(id, condition, automaticRule);              updated |= updateSnoozing(automaticRule); +            if (updated) { +                trigger = automaticRule.component; +            }          }          if (updated) { -            mHelper.setConfig(config, "conditionChanged"); +            mHelper.setConfig(config, trigger, "conditionChanged");          }      } -    private void evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions) { +    private void evaluateRule(ZenRule rule, ArraySet<Uri> current, ComponentName trigger, +            boolean processSubscriptions) {          if (rule == null || rule.conditionId == null) return;          final Uri id = rule.conditionId;          boolean isSystemCondition = false; @@ -146,7 +155,9 @@ public class ZenModeConditions implements ConditionProviders.Callback {          if (current != null) {              current.add(id);          } -        if (processSubscriptions) { +        if (processSubscriptions && ((trigger != null && trigger.equals(rule.component)) +                || isSystemCondition)) { +            if (DEBUG) Log.d(TAG, "Subscribing to " + rule.component);              if (mConditionProviders.subscribeIfNecessary(rule.component, rule.conditionId)) {                  synchronized (mSubscriptions) {                      mSubscriptions.put(rule.conditionId, rule.component); diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 669d5565534d..0c42f8ab8345 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -102,7 +102,7 @@ public class ZenModeHelper {      private final ZenModeFiltering mFiltering;      protected final RingerModeDelegate mRingerModeDelegate = new              RingerModeDelegate(); -    private final ZenModeConditions mConditions; +    @VisibleForTesting protected final ZenModeConditions mConditions;      private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();      private final Metrics mMetrics = new Metrics();      private final ConditionProviders.Config mServiceConfig; @@ -225,7 +225,7 @@ public class ZenModeHelper {              config.user = user;          }          synchronized (mConfig) { -            setConfigLocked(config, reason); +            setConfigLocked(config, null, reason);          }          cleanUpZenRules();      } @@ -312,7 +312,7 @@ public class ZenModeHelper {              ZenRule rule = new ZenRule();              populateZenRule(automaticZenRule, rule, true);              newConfig.automaticRules.put(rule.id, rule); -            if (setConfigLocked(newConfig, reason, true)) { +            if (setConfigLocked(newConfig, reason, rule.component, true)) {                  return rule.id;              } else {                  throw new AndroidRuntimeException("Could not create rule"); @@ -342,7 +342,7 @@ public class ZenModeHelper {              }              populateZenRule(automaticZenRule, rule, false);              newConfig.automaticRules.put(ruleId, rule); -            return setConfigLocked(newConfig, reason, true); +            return setConfigLocked(newConfig, reason, rule.component, true);          }      } @@ -360,7 +360,7 @@ public class ZenModeHelper {                  throw new SecurityException(                          "Cannot delete rules not owned by your condition provider");              } -            return setConfigLocked(newConfig, reason, true); +            return setConfigLocked(newConfig, reason, null, true);          }      } @@ -376,7 +376,7 @@ public class ZenModeHelper {                      newConfig.automaticRules.removeAt(i);                  }              } -            return setConfigLocked(newConfig, reason, true); +            return setConfigLocked(newConfig, reason, null, true);          }      } @@ -537,7 +537,7 @@ public class ZenModeHelper {                  newRule.enabler = caller;                  newConfig.manualRule = newRule;              } -            setConfigLocked(newConfig, reason, setRingerMode); +            setConfigLocked(newConfig, reason, null, setRingerMode);          }      } @@ -644,7 +644,7 @@ public class ZenModeHelper {              }              if (DEBUG) Log.d(TAG, reason);              synchronized (mConfig) { -                setConfigLocked(config, reason); +                setConfigLocked(config, null, reason);              }          }      } @@ -673,7 +673,7 @@ public class ZenModeHelper {          synchronized (mConfig) {              final ZenModeConfig newConfig = mConfig.copy();              newConfig.applyNotificationPolicy(policy); -            setConfigLocked(newConfig, "setNotificationPolicy"); +            setConfigLocked(newConfig, null, "setNotificationPolicy");          }      } @@ -697,7 +697,7 @@ public class ZenModeHelper {                      }                  }              } -            setConfigLocked(newConfig, "cleanUpZenRules"); +            setConfigLocked(newConfig, null, "cleanUpZenRules");          }      } @@ -710,17 +710,19 @@ public class ZenModeHelper {          }      } -    public boolean setConfigLocked(ZenModeConfig config, String reason) { -        return setConfigLocked(config, reason, true /*setRingerMode*/); +    public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, +            String reason) { +        return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);      } -    public void setConfig(ZenModeConfig config, String reason) { +    public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {          synchronized (mConfig) { -            setConfigLocked(config, reason); +            setConfigLocked(config, triggeringComponent, reason);          }      } -    private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) { +    private boolean setConfigLocked(ZenModeConfig config, String reason, +            ComponentName triggeringComponent, boolean setRingerMode) {          final long identity = Binder.clearCallingIdentity();          try {              if (config == null || !config.isValid()) { @@ -733,7 +735,8 @@ public class ZenModeHelper {                  if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);                  return true;              } -            mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config +            // may modify config +            mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);              mConfigs.put(config.user, config);              if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());              ZenLog.traceConfig(reason, mConfig, config); @@ -746,7 +749,7 @@ public class ZenModeHelper {                  dispatchOnPolicyChanged();              }              mConfig = config; -            mHandler.postApplyConfig(config, reason, setRingerMode); +            mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);              return true;          } catch (SecurityException e) {              Log.wtf(TAG, "Invalid rule in config", e); @@ -756,13 +759,14 @@ public class ZenModeHelper {          }      } -    private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { +    private void applyConfig(ZenModeConfig config, String reason, +            ComponentName triggeringComponent, boolean setRingerMode) {          final String val = Integer.toString(config.hashCode());          Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);          if (!evaluateZenMode(reason, setRingerMode)) {              applyRestrictions();  // evaluateZenMode will also apply restrictions if changed          } -        mConditions.evaluateConfig(config, true /*processSubscriptions*/); +        mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);      }      private int getZenModeSetting() { @@ -1260,13 +1264,16 @@ public class ZenModeHelper {          private final class ConfigMessageData {              public final ZenModeConfig config; +            public ComponentName triggeringComponent;              public final String reason;              public final boolean setRingerMode; -            ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) { +            ConfigMessageData(ZenModeConfig config, String reason, +                    ComponentName triggeringComponent, boolean setRingerMode) {                  this.config = config;                  this.reason = reason;                  this.setRingerMode = setRingerMode; +                this.triggeringComponent = triggeringComponent;              }          } @@ -1286,9 +1293,10 @@ public class ZenModeHelper {              sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);          } -        private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { +        private void postApplyConfig(ZenModeConfig config, String reason, +                ComponentName triggeringComponent, boolean setRingerMode) {              sendMessage(obtainMessage(MSG_APPLY_CONFIG, -                    new ConfigMessageData(config, reason, setRingerMode))); +                    new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));          }          @Override @@ -1303,7 +1311,7 @@ public class ZenModeHelper {                  case MSG_APPLY_CONFIG:                      ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;                      applyConfig(applyConfigData.config, applyConfigData.reason, -                            applyConfigData.setRingerMode); +                            applyConfigData.triggeringComponent, applyConfigData.setRingerMode);              }          }      } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index f082271ab094..c73870189002 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -22,11 +22,14 @@ import static android.content.Intent.ACTION_PACKAGE_CHANGED;  import static android.content.Intent.ACTION_PACKAGE_REMOVED;  import static android.content.Intent.ACTION_USER_ADDED;  import static android.content.Intent.ACTION_USER_REMOVED; +import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;  import static android.content.pm.PackageManager.SIGNATURE_MATCH;  import android.annotation.NonNull;  import android.annotation.Nullable;  import android.app.ActivityManager; +import android.app.ActivityThread;  import android.app.IActivityManager;  import android.content.BroadcastReceiver;  import android.content.Context; @@ -34,6 +37,7 @@ import android.content.Intent;  import android.content.IntentFilter;  import android.content.om.IOverlayManager;  import android.content.om.OverlayInfo; +import android.content.pm.ApplicationInfo;  import android.content.pm.IPackageManager;  import android.content.pm.PackageInfo;  import android.content.pm.PackageManagerInternal; @@ -269,13 +273,30 @@ public final class OverlayManagerService extends SystemService {      @Override      public void onBootPhase(int phase) { -        if (phase == PHASE_SYSTEM_SERVICES_READY) { +        if (phase == PHASE_SYSTEM_SERVICES_READY && mInitCompleteSignal != null) {              ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal,                      "Wait for OverlayManagerService init");              mInitCompleteSignal = null;          }      } +    public void updateSystemUiContext() { +        if (mInitCompleteSignal != null) { +            ConcurrentUtils.waitForFutureNoInterrupt(mInitCompleteSignal, +                    "Wait for OverlayManagerService init"); +            mInitCompleteSignal = null; +        } + +        final ApplicationInfo ai; +        try { +            ai = mPackageManager.mPackageManager.getApplicationInfo("android", +                    GET_SHARED_LIBRARY_FILES, UserHandle.USER_SYSTEM); +        } catch (RemoteException e) { +            throw e.rethrowAsRuntimeException(); +        } +        ActivityThread.currentActivityThread().handleSystemApplicationInfoChanged(ai); +    } +      private void initIfNeeded() {          final UserManager um = getContext().getSystemService(UserManager.class);          final List<UserInfo> users = um.getUsers(true /*excludeDying*/); diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index cf49d2a55d61..95c70d590b69 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -34,6 +34,7 @@ import android.util.Slog;  import com.android.internal.annotations.GuardedBy;  import com.android.internal.util.IndentingPrintWriter;  import com.android.server.pm.Installer.InstallerException; +import com.android.server.pm.dex.ArtManagerService;  import com.android.server.pm.dex.DexManager;  import com.android.server.pm.dex.DexoptOptions;  import com.android.server.pm.dex.DexoptUtils; @@ -289,7 +290,8 @@ public class PackageDexOptimizer {              mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags,                      compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo,                      false /* downgrade*/, pkg.applicationInfo.targetSdkVersion, -                    profileName, dexMetadataPath, getReasonName(compilationReason)); +                    profileName, dexMetadataPath, +                    getAugmentedReasonName(compilationReason, dexMetadataPath != null));              if (packageStats != null) {                  long endTime = System.currentTimeMillis(); @@ -302,6 +304,12 @@ public class PackageDexOptimizer {          }      } +    private String getAugmentedReasonName(int compilationReason, boolean useDexMetadata) { +        String annotation = useDexMetadata +                ? ArtManagerService.DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : ""; +        return getReasonName(compilationReason) + annotation; +    } +      /**       * Performs dexopt on the secondary dex {@code path} belonging to the app {@code info}.       * diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 29047e756f71..62c49e2d2ee5 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12344,7 +12344,8 @@ public class PackageManagerService extends IPackageManager.Stub              if (DEBUG_REMOVE) Log.d(TAG, "  Activities: " + r);          } -        mPermissionManager.removeAllPermissions(pkg, chatty); +        final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet()); +        mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty);          N = pkg.instrumentation.size();          r = null; @@ -21952,9 +21953,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());      //TODO: b/111402650      private void disableSkuSpecificApps() { -        if (!mIsUpgrade && !mFirstBoot) { -            return; -        }          String apkList[] = mContext.getResources().getStringArray(                  R.array.config_disableApksUnlessMatchedSku_apk_list);          String skuArray[] = mContext.getResources().getStringArray( @@ -21968,7 +21966,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());          }          for (String packageName : apkList) {              setSystemAppHiddenUntilInstalled(packageName, true); -            setSystemAppInstallState(packageName, false, ActivityManager.getCurrentUser()); +            for (UserInfo user : sUserManager.getUsers(false)) { +                setSystemAppInstallState(packageName, false, user.id); +            }          }      } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 0ba78226a38f..21daa39e05e0 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -519,6 +519,11 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {      private static final int TRON_COMPILATION_REASON_AB_OTA = 6;      private static final int TRON_COMPILATION_REASON_INACTIVE = 7;      private static final int TRON_COMPILATION_REASON_SHARED = 8; +    private static final int TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA = 9; + +    // The annotation to add as a suffix to the compilation reason when dexopt was +    // performed with dex metadata. +    public static final String DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION = "-dm";      /**       * Convert the compilation reason to an int suitable to be logged to TRON. @@ -534,6 +539,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub {              case "ab-ota" : return TRON_COMPILATION_REASON_AB_OTA;              case "inactive" : return TRON_COMPILATION_REASON_INACTIVE;              case "shared" : return TRON_COMPILATION_REASON_SHARED; +            // This is a special marker for dex metadata installation that does not +            // have an equivalent as a system property. +            case "install" + DEXOPT_REASON_WITH_DEX_METADATA_ANNOTATION : +                return TRON_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;              default: return TRON_COMPILATION_REASON_UNKNOWN;          }      } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java index a042fedf8b47..c3f23a81518a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java @@ -115,7 +115,11 @@ public abstract class PermissionManagerInternal {       */      public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);      public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty); -    public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); +    public abstract void removeAllPermissions( +            @NonNull PackageParser.Package pkg, +            @NonNull List<String> allPackageNames, +            @Nullable PermissionCallback permissionCallback, +            boolean chatty);      public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,              int callingUid, @Nullable PermissionCallback callback);      public abstract void removeDynamicPermission(@NonNull String permName, int callingUid, @@ -189,4 +193,4 @@ public abstract class PermissionManagerInternal {      /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */      public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName); -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index c51a72406b53..02c9049f008e 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -30,6 +30,7 @@ import android.Manifest;  import android.annotation.NonNull;  import android.annotation.Nullable;  import android.content.Context; +import android.content.pm.ApplicationInfo;  import android.content.pm.PackageManager;  import android.content.pm.PackageManagerInternal;  import android.content.pm.PackageParser; @@ -37,6 +38,7 @@ import android.content.pm.PermissionGroupInfo;  import android.content.pm.PermissionInfo;  import android.content.pm.PackageParser.Package;  import android.metrics.LogMaker; +import android.os.AsyncTask;  import android.os.Binder;  import android.os.Build;  import android.os.Handler; @@ -455,8 +457,9 @@ public class PermissionManagerService {                                          " to " + newPermissionGroupName);                                  try { -                                    revokeRuntimePermission(permissionName, packageName, false, -                                            Process.SYSTEM_UID, userId, permissionCallback); +                                    revokeRuntimePermission(permissionName, packageName, +                                            mSettings.getPermission(permissionName), false, +                                            Process.SYSTEM_UID, userId, permissionCallback, false);                                  } catch (IllegalArgumentException e) {                                      Slog.e(TAG, "Could not revoke " + permissionName + " from "                                              + packageName, e); @@ -549,9 +552,59 @@ public class PermissionManagerService {      } -    private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) { +    private void revokeAllPermissions( +            @NonNull List<BasePermission> bps, +            @NonNull List<String> allPackageNames, +            @Nullable PermissionCallback permissionCallback) { +        AsyncTask.execute(() -> { +            final int numRemovedPermissions = bps.size(); +            for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) { +                final int[] userIds = mUserManagerInt.getUserIds(); +                final int numUserIds = userIds.length; + +                final int numPackages = allPackageNames.size(); +                for (int packageNum = 0; packageNum < numPackages; packageNum++) { +                    final String packageName = allPackageNames.get(packageNum); +                    final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo( +                            packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM); +                    if (applicationInfo != null +                            && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { +                        continue; +                    } +                    for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { +                        final int userId = userIds[userIdNum]; +                        final String permissionName = bps.get(permissionNum).getName(); +                        if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM, +                                userId) == PackageManager.PERMISSION_GRANTED) { +                            try { +                                revokeRuntimePermission( +                                        permissionName, +                                        packageName, +                                        bps.get(permissionNum), +                                        false, +                                        Process.SYSTEM_UID, +                                        userId, +                                        permissionCallback, +                                        true); +                            } catch (IllegalArgumentException e) { +                                Slog.e(TAG, "Could not revoke " + permissionName + " from " +                                        + packageName, e); +                            } +                        } +                    } +                } +            } +        }); +    } + +    private void removeAllPermissions( +            @NonNull PackageParser.Package pkg, +            @NonNull List<String> allPackageNames, +            @Nullable PermissionCallback permissionCallback, +            boolean chatty) {          synchronized (mLock) {              int N = pkg.permissions.size(); +            List<BasePermission> bps = new ArrayList<BasePermission>(N);              StringBuilder r = null;              for (int i=0; i<N; i++) {                  PackageParser.Permission p = pkg.permissions.get(i); @@ -560,6 +613,9 @@ public class PermissionManagerService {                      bp = mSettings.mPermissionTrees.get(p.info.name);                  }                  if (bp != null && bp.isPermission(p)) { +                    if ((p.info.getProtection() & PermissionInfo.PROTECTION_DANGEROUS) != 0) { +                        bps.add(bp); +                    }                      bp.setPermission(null);                      if (DEBUG_REMOVE && chatty) {                          if (r == null) { @@ -578,6 +634,7 @@ public class PermissionManagerService {                      }                  }              } +            revokeAllPermissions(bps, allPackageNames, permissionCallback);              if (r != null) {                  if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);              } @@ -1490,9 +1547,10 @@ public class PermissionManagerService {          }      } - -    private void revokeRuntimePermission(String permName, String packageName, -            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) { +     +    private void revokeRuntimePermission(String permName, String packageName, BasePermission bp, +            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback, +            boolean permissionRemoved) {          if (!mUserManagerInt.exists(userId)) {              Log.e(TAG, "No such user:" + userId);              return; @@ -1517,7 +1575,7 @@ public class PermissionManagerService {          if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {              throw new IllegalArgumentException("Unknown package: " + packageName);          } -        final BasePermission bp = mSettings.getPermissionLocked(permName); +          if (bp == null) {              throw new IllegalArgumentException("Unknown permission: " + permName);          } @@ -2073,8 +2131,10 @@ public class PermissionManagerService {              PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);          }          @Override -        public void removeAllPermissions(Package pkg, boolean chatty) { -            PermissionManagerService.this.removeAllPermissions(pkg, chatty); +        public void removeAllPermissions(Package pkg, List<String> allPackageNames, +                PermissionCallback permissionCallback, boolean chatty) { +            PermissionManagerService.this.removeAllPermissions( +                    pkg, allPackageNames, permissionCallback, chatty);          }          @Override          public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid, @@ -2110,7 +2170,8 @@ public class PermissionManagerService {                  boolean overridePolicy, int callingUid, int userId,                  PermissionCallback callback) {              PermissionManagerService.this.revokeRuntimePermission(permName, packageName, -                    overridePolicy, callingUid, userId, callback); +                    mSettings.getPermission(permName), overridePolicy, callingUid, userId, +                    callback, false);          }          @Override          public void updatePermissions(String packageName, Package pkg, boolean replaceGrant, diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java index eca6f9f1ec47..14c985c090a3 100644 --- a/services/core/java/com/android/server/policy/BarController.java +++ b/services/core/java/com/android/server/policy/BarController.java @@ -196,7 +196,7 @@ public class BarController {      }      protected boolean skipAnimation() { -        return false; +        return !mWin.isDrawnLw();      }      private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dfb617999668..9a741bcfc3d6 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -76,6 +76,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CO  import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;  import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;  import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_BAR_EXPANDED;  import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;  import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;  import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; @@ -4397,17 +4398,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {              if (isKeyguardShowingAndNotOccluded()) {                  // don't launch home if keyguard showing                  return; -            } else if (mKeyguardOccluded && mKeyguardDelegate.isShowing()) { -                mKeyguardDelegate.dismiss(new KeyguardDismissCallback() { -                    @Override -                    public void onDismissSucceeded() throws RemoteException { -                        mHandler.post(() -> { -                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); -                        }); -                    } -                }, null /* message */); -                return; -            } else if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) { +            } + +            if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {                  // when in keyguard restricted mode, must first verify unlock                  // before launching home                  mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { @@ -4692,8 +4685,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {                  navTranslucent &= areTranslucentBarsAllowed();              }              boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null -                    && mStatusBar.getAttrs().height == MATCH_PARENT -                    && mStatusBar.getAttrs().width == MATCH_PARENT; +                    && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0;              // When the navigation bar isn't visible, we put up a fake input window to catch all              // touch events. This way we can detect when the user presses anywhere to bring back the @@ -5696,7 +5688,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {          }          // Take note if a window wants to acquire a sleep token. -        if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0 +        if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0                  && win.canAcquireSleepToken()) {              mWindowSleepTokenNeeded = true;          } @@ -5752,9 +5744,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {                  mStatusBarController.setShowTransparent(true /* transparent */);              } -            WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); -            boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT -                    && statusBarAttrs.width == MATCH_PARENT; +            boolean statusBarExpanded = +                    (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_STATUS_BAR_EXPANDED) != 0;              boolean topAppHidesStatusBar = topAppHidesStatusBar();              if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent                      || statusBarExpanded) { diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 44136661bee5..f9f4bbfc8eb0 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -46,7 +46,6 @@ import android.os.RemoteException;  import android.os.SystemClock;  import android.os.UserHandle;  import android.os.UserManager; -import android.os.storage.StorageManager;  import android.provider.Settings;  import android.service.trust.TrustAgentService;  import android.text.TextUtils; @@ -60,7 +59,6 @@ import android.view.IWindowManager;  import android.view.WindowManagerGlobal;  import com.android.internal.annotations.GuardedBy;  import com.android.internal.content.PackageMonitor; -import com.android.internal.policy.IKeyguardDismissCallback;  import com.android.internal.util.DumpUtils;  import com.android.internal.widget.LockPatternUtils;  import com.android.server.SystemService; @@ -431,13 +429,20 @@ public class TrustManagerService extends SystemService {          for (int i = 0; i < userInfos.size(); i++) {              UserInfo info = userInfos.get(i); -            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove -                    || !info.supportsSwitchToByUser()) { +            if (info == null || info.partial || !info.isEnabled() || info.guestToRemove) {                  continue;              }              int id = info.id;              boolean secure = mLockPatternUtils.isSecure(id); + +            if (!info.supportsSwitchToByUser()) { +                if (info.isManagedProfile() && !secure) { +                    setDeviceLockedForUser(id, false); +                } +                continue; +            } +              boolean trusted = aggregateIsTrusted(id);              boolean showingKeyguard = true;              boolean fingerprintAuthenticated = false; @@ -992,7 +997,8 @@ public class TrustManagerService extends SystemService {              enforceReportPermission();              final long identity = Binder.clearCallingIdentity();              try { -                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { +                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) +                        && mLockPatternUtils.isSecure(userId)) {                      synchronized (mDeviceLockedForUser) {                          mDeviceLockedForUser.put(userId, locked);                      } diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index b2a12bef5283..86f328d248db 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -31,11 +31,13 @@ import android.os.IBinder;  import android.os.Debug;  import android.util.ArrayMap;  import android.util.Slog; +import android.view.Choreographer;  import android.view.animation.AnimationUtils;  import android.view.animation.Interpolator;  import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.graphics.SfVsyncFrameCallbackProvider;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy; @@ -112,6 +114,7 @@ public class BoundsAnimationController {      private final Interpolator mFastOutSlowInInterpolator;      private boolean mFinishAnimationAfterTransition = false;      private final AnimationHandler mAnimationHandler; +    private Choreographer mChoreographer;      private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000; @@ -123,6 +126,12 @@ public class BoundsAnimationController {          mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,                  com.android.internal.R.interpolator.fast_out_slow_in);          mAnimationHandler = animationHandler; +        if (animationHandler != null) { +            // If an animation handler is provided, then ensure that it runs on the sf vsync tick +            handler.runWithScissors(() -> mChoreographer = Choreographer.getSfInstance(), +                    0 /* timeout */); +            animationHandler.setProvider(new SfVsyncFrameCallbackProvider(mChoreographer)); +        }      }      @VisibleForTesting diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2887e5ef9061..2941e93d12dc 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1775,8 +1775,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo          final int newDensity = mDisplayInfo.logicalDensityDpi;          final DisplayCutout newCutout = mDisplayInfo.displayCutout; -        final boolean displayMetricsChanged = mInitialDisplayWidth != newWidth -                || mInitialDisplayHeight != newHeight +        final boolean sizeChanged = mInitialDisplayWidth != newWidth +                || mInitialDisplayHeight != newHeight; +        final boolean displayMetricsChanged = sizeChanged                  || mInitialDisplayDensity != mDisplayInfo.logicalDensityDpi                  || !Objects.equals(mInitialDisplayCutout, newCutout); @@ -1798,6 +1799,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo              mInitialDisplayCutout = newCutout;              mService.reconfigureDisplayLocked(this);          } + +        if (isDefaultDisplay && sizeChanged) { +            mService.mH.post(mService.mAmInternal::notifyDefaultDisplaySizeChanged); +        }      }      /** Sets the maximum width the screen resolution can be */ diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java index f25ec5cd935e..efb43a6b90cf 100644 --- a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java +++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java @@ -21,6 +21,7 @@ import static android.view.Surface.ROTATION_90;  import android.graphics.Matrix;  import android.view.DisplayInfo; +import android.view.Surface.Rotation;  import com.android.server.wm.utils.CoordinateTransforms; @@ -65,6 +66,16 @@ public class ForcedSeamlessRotator {      }      /** +     * Returns the rotation of the display before it started rotating. +     * +     * @return the old rotation of the display +     */ +    @Rotation +    public int getOldRotation() { +        return mOldRotation; +    } + +    /**       * Removes the transform to the window token's surface that undoes the effect of the global       * display rotation.       * @@ -75,12 +86,14 @@ public class ForcedSeamlessRotator {      public void finish(WindowToken token, WindowState win) {          mTransform.reset();          token.getPendingTransaction().setMatrix(token.mSurfaceControl, mTransform, mFloat9); -        token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl, -                win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), -                win.getFrameNumber()); -        win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl, -                win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), -                win.getFrameNumber()); +        if (win.mWinAnimator.mSurfaceController != null) { +            token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl, +                    win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), +                    win.getFrameNumber()); +            win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl, +                    win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(), +                    win.getFrameNumber()); +        }      }      public void dump(PrintWriter pw) { diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index fa8a5c66aeea..755a571cf5f7 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -37,6 +37,7 @@ import android.view.DisplayInfo;  import android.view.Surface;  import android.view.Surface.OutOfResourcesException;  import android.view.SurfaceControl; +import android.view.SurfaceControl.Transaction;  import android.view.SurfaceSession;  import android.view.animation.Animation;  import android.view.animation.AnimationUtils; @@ -268,6 +269,12 @@ class ScreenRotationAnimation {                      .setSecure(isSecure)                      .build(); +            // In case display bounds change, screenshot buffer and surface may mismatch so set a +            // scaling mode. +            Transaction t2 = new Transaction(); +            t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW); +            t2.apply(true /* sync */); +              // capture a screenshot into the surface we just created              // TODO(multidisplay): we should use the proper display              final int displayId = SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8bc224636c1e..8b4a2dd36e6c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1005,7 +1005,6 @@ public class WindowManagerService extends IWindowManager.Stub          mAppTransition.registerListenerLocked(mActivityManagerAppTransitionNotifier);          final AnimationHandler animationHandler = new AnimationHandler(); -        animationHandler.setProvider(new SfVsyncFrameCallbackProvider());          mBoundsAnimationController = new BoundsAnimationController(context, mAppTransition,                  AnimationThread.getHandler(), animationHandler); @@ -6221,6 +6220,17 @@ public class WindowManagerService extends IWindowManager.Stub      }      /** +     * Returns true if the callingUid has any window currently visible to the user. +     */ +    public boolean isAnyWindowVisibleForUid(int callingUid) { +        synchronized (mWindowMap) { +            return mRoot.forAllWindows(w -> { +                return w.getOwningUid() == callingUid && w.isVisible(); +            }, true /* traverseTopToBottom */); +        } +    } + +    /**       * Called when a task has been removed from the recent tasks list.       * <p>       * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 009f3930d02e..1ae680f793ca 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -681,6 +681,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP      void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) {          if (mForceSeamlesslyRotate) { +            if (mPendingForcedSeamlessRotate != null) { +                oldRotation = mPendingForcedSeamlessRotate.getOldRotation(); +            } +              mPendingForcedSeamlessRotate = new ForcedSeamlessRotator(                      oldRotation, rotation, getDisplayInfo());              mPendingForcedSeamlessRotate.unrotate(this.mToken); diff --git a/services/core/java/com/android/server/wm/utils/InsetUtils.java b/services/core/java/com/android/server/wm/utils/InsetUtils.java index b4a998add374..c8600dd151d2 100644 --- a/services/core/java/com/android/server/wm/utils/InsetUtils.java +++ b/services/core/java/com/android/server/wm/utils/InsetUtils.java @@ -17,6 +17,7 @@  package com.android.server.wm.utils;  import android.graphics.Rect; +import android.view.Surface;  /**   * Utility methods to handle insets represented as rects. @@ -27,6 +28,32 @@ public class InsetUtils {      }      /** +     * Transforms insets given in one rotation into insets in a different rotation. +     * +     * @param inOutInsets the insets to transform, is set to the transformed insets +     * @param rotationDelta the delta between the new and old rotation. +     *                      Must be one of Surface.ROTATION_0/90/180/270. +     */ +    public static void rotateInsets(Rect inOutInsets, int rotationDelta) { +        final Rect r = inOutInsets; +        switch (rotationDelta) { +            case Surface.ROTATION_0: +                return; +            case Surface.ROTATION_90: +                r.set(r.top, r.right, r.bottom, r.left); +                break; +            case Surface.ROTATION_180: +                r.set(r.right, r.bottom, r.left, r.top); +                break; +            case Surface.ROTATION_270: +                r.set(r.bottom, r.left, r.top, r.right); +                break; +            default: +                throw new IllegalArgumentException("Unknown rotation: " + rotationDelta); +        } +    } + +    /**       * Adds {@code insetsToAdd} to {@code inOutInsets}.       */      public static void addInsets(Rect inOutInsets, Rect insetsToAdd) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b74a582db2de..6ee7d4931c18 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4572,10 +4572,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {          enforceFullCrossUsersPermission(userHandle);          synchronized (getLockObject()) {              if (!isCallerWithSystemUid()) { -                // This API can only be called by an active device admin, -                // so try to retrieve it to check that the caller is one. -                getActiveAdminForCallerLocked( -                        null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); +                // This API can be called by an active device admin or by keyguard code. +                if (mContext.checkCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE) +                        != PackageManager.PERMISSION_GRANTED) { +                    getActiveAdminForCallerLocked( +                            null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent); +                }              }              DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, parent)); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 82a28954a8c6..e91780239c7f 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -29,6 +29,7 @@ import android.content.res.Configuration;  import android.content.res.Resources.Theme;  import android.database.sqlite.SQLiteCompatibilityWalFlags;  import android.database.sqlite.SQLiteGlobal; +import android.hardware.display.DisplayManagerInternal;  import android.os.BaseBundle;  import android.os.Binder;  import android.os.Build; @@ -681,9 +682,17 @@ public final class SystemServer {          // Manages Overlay packages          traceBeginAndSlog("StartOverlayManagerService"); -        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer)); +        OverlayManagerService overlayManagerService = new OverlayManagerService( +                mSystemContext, installer); +        mSystemServiceManager.startService(overlayManagerService);          traceEnd(); +        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) { +            // DisplayManager needs the overlay immediately. +            overlayManagerService.updateSystemUiContext(); +            LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged(); +        } +          // The sensor service needs access to package manager service, app ops          // service, and permissions service, therefore we start it after them.          // Start sensor service in a separate thread. Completion should be checked diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java index 1520859d4aac..8d056fc4a8c0 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java @@ -53,6 +53,7 @@ import android.view.Gravity;  import org.junit.runner.RunWith;  import org.junit.Test; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;  import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;  import static com.android.server.am.ActivityManagerService.ANIMATE; @@ -62,11 +63,13 @@ import static org.mockito.Mockito.any;  import static org.mockito.Mockito.anyBoolean;  import static org.mockito.Mockito.anyInt;  import static org.mockito.Mockito.anyObject; +import static org.mockito.Mockito.clearInvocations;  import static org.mockito.Mockito.doAnswer;  import static org.mockito.Mockito.doNothing;  import static org.mockito.Mockito.doReturn;  import static org.mockito.Mockito.eq;  import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never;  import static org.mockito.Mockito.spy;  import static org.mockito.Mockito.verify;  import static org.mockito.Mockito.times; @@ -91,6 +94,7 @@ public class ActivityStarterTests extends ActivityTestsBase {      private ActivityManagerService mService;      private ActivityStarter mStarter;      private ActivityStartController mController; +    private ActivityMetricsLogger mActivityMetricsLogger;      private static final int PRECONDITION_NO_CALLER_APP = 1;      private static final int PRECONDITION_NO_INTENT_COMPONENT = 1 << 1; @@ -104,11 +108,17 @@ public class ActivityStarterTests extends ActivityTestsBase {      private static final int PRECONDITION_CANNOT_START_ANY_ACTIVITY = 1 << 9;      private static final int PRECONDITION_DISALLOW_APP_SWITCHING = 1 << 10; +    private static final int FAKE_CALLING_UID = 666; +    private static final int FAKE_REAL_CALLING_UID = 667; +    private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude"; +      @Override      public void setUp() throws Exception {          super.setUp();          mService = createActivityManagerService();          mController = mock(ActivityStartController.class); +        mActivityMetricsLogger = mock(ActivityMetricsLogger.class); +        clearInvocations(mActivityMetricsLogger);          mStarter = new ActivityStarter(mController, mService, mService.mStackSupervisor,                  mock(ActivityStartInterceptor.class));      } @@ -471,4 +481,46 @@ public class ActivityStarterTests extends ActivityTestsBase {              assertTrue(stack.getAllTasks().isEmpty());          }      } + +    /** +     * This test ensures that activity starts are not being logged when the logging is disabled. +     */ +    @Test +    public void testActivityStartsLogging_noLoggingWhenDisabled() { +        doReturn(false).when(mService).isActivityStartsLoggingEnabled(); +        doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); + +        ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK); +        starter.setReason("testActivityStartsLogging_noLoggingWhenDisabled").execute(); + +        // verify logging wasn't done +        verify(mActivityMetricsLogger, never()).logActivityStart(any(), any(), any(), anyInt(), +                any(), anyInt(), anyBoolean(), anyInt(), anyInt(), anyBoolean(), anyInt(), any(), +                anyInt(), anyBoolean(), any(), anyBoolean()); +    } + +    /** +     * This test ensures that activity starts are being logged when the logging is enabled. +     */ +    @Test +    public void testActivityStartsLogging_logsWhenEnabled() { +        // note: conveniently this package doesn't have any activity visible +        doReturn(true).when(mService).isActivityStartsLoggingEnabled(); +        doReturn(mActivityMetricsLogger).when(mService.mStackSupervisor).getActivityMetricsLogger(); + +        ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK) +                .setCallingUid(FAKE_CALLING_UID) +                .setRealCallingUid(FAKE_REAL_CALLING_UID) +                .setCallingPackage(FAKE_CALLING_PACKAGE) +                .setOriginatingPendingIntent(null); + +        starter.setReason("testActivityStartsLogging_logsWhenEnabled").execute(); + +        // verify the above activity start was logged +        verify(mActivityMetricsLogger, times(1)).logActivityStart(any(), any(), any(), +                eq(FAKE_CALLING_UID), eq(FAKE_CALLING_PACKAGE), anyInt(), anyBoolean(), +                eq(FAKE_REAL_CALLING_UID), anyInt(), anyBoolean(), anyInt(), +                eq(ActivityBuilder.getDefaultComponent().getPackageName()), anyInt(), anyBoolean(), +                any(), eq(false)); +    }  } diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java index d0f0fe315bcf..08bcc3d751f2 100644 --- a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java @@ -16,6 +16,11 @@  package com.android.server.wm.utils; +import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90; +import static android.view.Surface.ROTATION_0; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; +  import static junit.framework.Assert.assertEquals;  import android.graphics.Rect; @@ -39,5 +44,29 @@ public class InsetUtilsTest {          InsetUtils.addInsets(rect1, rect2);          assertEquals(new Rect(60, 80, 100, 120), rect1);      } + +    @Test +    public void rotate() { +        final Rect original = new Rect(1, 2, 3, 4); + +        assertEquals("rot0", original, rotateCopy(original, ROTATION_0)); + +        final Rect rot90 = rotateCopy(original, ROTATION_90); +        assertEquals("rot90", new Rect(2, 3, 4, 1), rot90); + +        final Rect rot180 = rotateCopy(original, ROTATION_180); +        assertEquals("rot180", new Rect(3, 4, 1, 2), rot180); +        assertEquals("rot90(rot90)=rot180", rotateCopy(rot90, ROTATION_90), rot180); + +        final Rect rot270 = rotateCopy(original, ROTATION_270); +        assertEquals("rot270", new Rect(4, 1, 2, 3), rot270); +        assertEquals("rot90(rot180)=rot270", rotateCopy(rot180, ROTATION_90), rot270); +    } + +    private static Rect rotateCopy(Rect insets, int rotationDelta) { +        final Rect copy = new Rect(insets); +        InsetUtils.rotateInsets(copy, rotationDelta); +        return copy; +    }  } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index afc12636007f..8222c386c0d9 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.times;  import static org.mockito.Mockito.verify;  import static org.mockito.Mockito.when; +import android.app.AppGlobals;  import android.app.AppOpsManager;  import android.app.NotificationManager;  import android.content.ComponentName; @@ -49,8 +50,10 @@ import android.media.AudioManager;  import android.media.AudioManagerInternal;  import android.media.VolumePolicy;  import android.media.AudioSystem; +import android.net.Uri;  import android.provider.Settings;  import android.provider.Settings.Global; +import android.service.notification.Condition;  import android.service.notification.ZenModeConfig;  import android.service.notification.ZenModeConfig.ScheduleInfo;  import android.test.suitebuilder.annotation.SmallTest; @@ -61,6 +64,7 @@ import android.util.Xml;  import com.android.internal.R;  import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; +import com.android.server.notification.ManagedServices.UserProfiles;  import com.android.internal.util.FastXmlSerializer;  import com.android.server.UiServiceTestCase;  import android.util.Slog; @@ -83,7 +87,7 @@ import java.io.ByteArrayOutputStream;  @TestableLooper.RunWithLooper  public class ZenModeHelperTest extends UiServiceTestCase { -    @Mock ConditionProviders mConditionProviders; +    ConditionProviders mConditionProviders;      @Mock NotificationManager mNotificationManager;      @Mock private Resources mResources;      private TestableLooper mTestableLooper; @@ -103,6 +107,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {          when(mResources.getString(R.string.zen_mode_default_events_name)).thenReturn("events");          when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager); +        mConditionProviders = new ConditionProviders(mContext, new UserProfiles(), +                AppGlobals.getPackageManager()); +        mConditionProviders.addSystemProvider(new CountdownConditionProvider());          mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),                  mConditionProviders));      } @@ -116,7 +123,7 @@ public class ZenModeHelperTest extends UiServiceTestCase {          mZenModeHelperSpy.writeXml(serializer, forBackup, version);          serializer.endDocument();          serializer.flush(); -        mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml"); +        mZenModeHelperSpy.setConfig(new ZenModeConfig(), null, "writing xml");          return baos;      } @@ -813,6 +820,30 @@ public class ZenModeHelperTest extends UiServiceTestCase {          setupZenConfigMaintained();      } +    @Test +    public void testCountdownConditionSubscription() throws Exception { +        ZenModeConfig config = new ZenModeConfig(); +        mZenModeHelperSpy.mConfig = config; +        mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true); +        assertEquals(0, mZenModeHelperSpy.mConditions.mSubscriptions.size()); + +        mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule(); +        Uri conditionId = ZenModeConfig.toCountdownConditionId(9000000, false); +        mZenModeHelperSpy.mConfig.manualRule.conditionId = conditionId; +        mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("android", +                CountdownConditionProvider.class.getName()); +        mZenModeHelperSpy.mConfig.manualRule.condition = new Condition(conditionId, "", "", "", 0, +                Condition.STATE_TRUE, Condition.FLAG_RELEVANT_NOW); +        mZenModeHelperSpy.mConfig.manualRule.enabled = true; +        ZenModeConfig originalConfig = mZenModeHelperSpy.mConfig.copy(); + +        mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true); + +        assertEquals(true, ZenModeConfig.isValidCountdownConditionId(conditionId)); +        assertEquals(originalConfig, mZenModeHelperSpy.mConfig); +        assertEquals(1, mZenModeHelperSpy.mConditions.mSubscriptions.size()); +    } +      private void setupZenConfig() {          mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;          mZenModeHelperSpy.mConfig.allowAlarms = false; diff --git a/test-base/Android.bp b/test-base/Android.bp index d25b47727c0b..0b8a02a815d9 100644 --- a/test-base/Android.bp +++ b/test-base/Android.bp @@ -19,9 +19,8 @@  // This contains the junit.framework and android.test classes that were in  // Android API level 25 excluding those from android.test.runner.  // Also contains the com.android.internal.util.Predicate[s] classes. -java_library { +java_sdk_library {      name: "android.test.base", -    installable: true,      srcs: ["src/**/*.java"], @@ -29,11 +28,38 @@ java_library {        javacflags: ["-Xep:DepAnn:ERROR"],      }, +    hostdex: true, + +    api_packages: [ +        "android.test", +        "android.test.suitebuilder.annotation", +        "com.android.internal.util", +        "junit.framework", +    ], + +    droiddoc_options: ["stubsourceonly"], +    compile_dex: true, +} + +// Build the android.test.base_static library +// ========================================== +// This is only intended for inclusion in the android.test.runner-minus-junit, +// robolectric_android-all-stub and repackaged.android.test.* libraries. +// Must not be used elewhere. +java_library_static { +    name: "android.test.base_static", +    installable: false, + +    srcs: ["src/**/*.java"], + +    errorprone: { +        javacflags: ["-Xep:DepAnn:ERROR"], +    }, +      // Needs to be consistent with the repackaged version of this make target.      java_version: "1.8",      sdk_version: "current", -    hostdex: true,  }  // Build the legacy-test library @@ -46,7 +72,7 @@ java_library {      installable: true,      sdk_version: "current", -    static_libs: ["android.test.base"], +    static_libs: ["android.test.base_static"],  }  // Build the repackaged.android.test.base library @@ -57,7 +83,7 @@ java_library_static {      name: "repackaged.android.test.base",      sdk_version: "current", -    static_libs: ["android.test.base"], +    static_libs: ["android.test.base_static"],      jarjar_rules: "jarjar-rules.txt",      // Pin java_version until jarjar is certified to support later versions. http://b/72703434 @@ -84,38 +110,3 @@ java_library_static {      ],  } -droiddoc { -    name: "android-test-base-api-stubs-gen-docs", -    srcs: [ -        "src/**/*.java", -    ], -    custom_template: "droiddoc-templates-sdk", -    installable: false, -    args: "-stubpackages android.test:" + -          "android.test.suitebuilder.annotation:" + -          "com.android.internal.util:" + -          "junit.framework -stubsourceonly -nodocs", -    sdk_version: "current", -    api_tag_name: "ANDROID_TEST_BASE", -    api_filename: "android-test-base-api.txt", -    removed_api_filename: "android-test-base-removed.txt", -} - -// Build the android.test.base.stubs library -// ========================================= -java_library_static { -    name: "android.test.base.stubs", -    srcs: [ -        ":android-test-base-api-stubs-gen-docs", -    ], -    product_variables: { -        pdk: { -            enabled: false, -        }, -        unbundled_build: { -            enabled: false, -        }, -    }, -    sdk_version: "current", -    compile_dex: true, -} diff --git a/test-base/Android.mk b/test-base/Android.mk index baf5726ff8bd..a9d30cf3131a 100644 --- a/test-base/Android.mk +++ b/test-base/Android.mk @@ -16,50 +16,6 @@  LOCAL_PATH:= $(call my-dir) -# For unbundled build we'll use the prebuilt jar from prebuilts/sdk. -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) - -ANDROID_TEST_BASE_API_FILE := $(LOCAL_PATH)/api/android-test-base-current.txt -ANDROID_TEST_BASE_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-base-removed.txt - -full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.base.stubs,,COMMON)/classes.jar -# Archive a copy of the classes.jar in SDK build. -$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.base.stubs.jar) - -# Check that the android.test.base.stubs library has not changed -# ============================================================== - -# Check that the API we're building hasn't changed from the not-yet-released -# SDK version. -$(eval $(call check-api, \ -    check-android-test-base-api-current, \ -    $(ANDROID_TEST_BASE_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE), \ -    $(ANDROID_TEST_BASE_REMOVED_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE), \ -    -error 2 -error 3 -error 4 -error 5 -error 6 \ -    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -    -error 25 -error 26 -error 27, \ -    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_base.txt, \ -    check-android-test-base-api, \ -    $(OUT_DOCS)/android-test-base-api-stubs-gen-docs-stubs.srcjar \ -    )) - -.PHONY: check-android-test-base-api -checkapi: check-android-test-base-api - -.PHONY: update-android-test-base-api -update-api: update-android-test-base-api - -update-android-test-base-api: $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) | $(ACP) -	@echo Copying current.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_API_FILE) $(ANDROID_TEST_BASE_API_FILE) -	@echo Copying removed.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_BASE_REMOVED_API_FILE) $(ANDROID_TEST_BASE_REMOVED_API_FILE) - -endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true -  ifeq ($(HOST_OS),linux)  # Build the legacy-performance-test-hostdex library  # ================================================= diff --git a/test-base/api/apicheck_msg_android_test_base.txt b/test-base/api/apicheck_msg_android_test_base.txt deleted file mode 100644 index 144aecc21bce..000000000000 --- a/test-base/api/apicheck_msg_android_test_base.txt +++ /dev/null @@ -1,17 +0,0 @@ - -****************************** -You have tried to change the API from what has been previously approved. - -To make these errors go away, you have two choices: -   1) You can add "@hide" javadoc comments to the methods, etc. listed in the -      errors above. - -   2) You can update android-test-base-current.txt by executing the following command: -         make update-android-test-base-api - -      To submit the revised android-test-base-current.txt to the main Android repository, -      you will need approval. -****************************** - - - diff --git a/test-base/api/android-test-base-current.txt b/test-base/api/current.txt index 7ebd6aa8a4a2..7ebd6aa8a4a2 100644 --- a/test-base/api/android-test-base-current.txt +++ b/test-base/api/current.txt diff --git a/test-base/api/android-test-base-removed.txt b/test-base/api/removed.txt index e69de29bb2d1..e69de29bb2d1 100644 --- a/test-base/api/android-test-base-removed.txt +++ b/test-base/api/removed.txt diff --git a/test-mock/api/android-test-mock-system-removed.txt b/test-base/api/system-current.txt index e69de29bb2d1..e69de29bb2d1 100644 --- a/test-mock/api/android-test-mock-system-removed.txt +++ b/test-base/api/system-current.txt diff --git a/test-runner/api/android-test-runner-removed.txt b/test-base/api/system-removed.txt index e69de29bb2d1..e69de29bb2d1 100644 --- a/test-runner/api/android-test-runner-removed.txt +++ b/test-base/api/system-removed.txt diff --git a/test-base/api/test-current.txt b/test-base/api/test-current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-base/api/test-current.txt diff --git a/test-base/api/test-removed.txt b/test-base/api/test-removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-base/api/test-removed.txt diff --git a/test-legacy/Android.bp b/test-legacy/Android.bp index d2af8a9f1c82..833c714f07b0 100644 --- a/test-legacy/Android.bp +++ b/test-legacy/Android.bp @@ -25,7 +25,7 @@ java_library_static {      static_libs: [          "android.test.base-minus-junit",          "android.test.runner-minus-junit", -        "android.test.mock", +        "android.test.mock.impl",      ],      no_framework_libs: true, diff --git a/test-mock/Android.bp b/test-mock/Android.bp index 8d3faaef9f6b..5eba01779f46 100644 --- a/test-mock/Android.bp +++ b/test-mock/Android.bp @@ -16,95 +16,15 @@  // Build the android.test.mock library  // =================================== -java_library { +java_sdk_library {      name: "android.test.mock", -    installable: true, -    java_version: "1.8",      srcs: ["src/**/*.java"], -    no_framework_libs: true, -    libs: [ -        "framework", +    api_packages: [ +        "android.test.mock",      ], -} - -doc_defaults { -    name:"android.test.mock.docs-defaults", -    srcs: ["src/android/test/mock/**/*.java"], -    // Includes the main framework source to ensure that doclava has access to the -    // visibility information for the base classes of the mock classes. Without it -    // otherwise hidden methods could be visible. -    srcs_lib: "framework", -    srcs_lib_whitelist_dirs: ["core/java"],      srcs_lib_whitelist_pkgs: ["android"], -    libs: [ -        "core-oj", -        "core-libart", -        "framework", -        "conscrypt", -        "okhttp", -        "bouncycastle", -        "ext", -    ], -    local_sourcepaths: ["src/android/test/mock"], -    custom_template: "droiddoc-templates-sdk", -    installable: false, -} - -android_test_mock_docs_args = -    "-hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 " + -    "-stubpackages android.test.mock " + -    "-nodocs " - -droiddoc { -    name: "android.test.mock.docs", -    defaults: ["android.test.mock.docs-defaults"], - -    api_tag_name: "ANDROID_TEST_MOCK", -    api_filename: "api/android-test-mock-current.txt", -    removed_api_filename: "api/android-test-mock-removed.txt", - -    args: android_test_mock_docs_args, -} - -droiddoc { -    name: "android.test.mock.docs-system", -    defaults: ["android.test.mock.docs-defaults"], - -    api_tag_name: "ANDROID_TEST_MOCK_SYSTEM", -    api_filename: "api/android-test-mock-system-current.txt", -    removed_api_filename: "api/android-test-mock-system-removed.txt", - -    args: android_test_mock_docs_args + -        "-showAnnotation android.annotation.SystemApi ", -} - -java_library_static { -    name: "android.test.mock.stubs", -    srcs: [":android.test.mock.docs"], -    sdk_version: "current", -    product_variables: { -        unbundled_build: { -            // Unbundled apps will use the prebuilt one -            // prebuilts/sdk/current -            enabled: false, -        }, -    }, -    compile_dex: true, -} - -java_library_static { -    name: "android.test.mock.stubs-system", -    srcs: [":android.test.mock.docs-system"], -    sdk_version: "system_current", -    product_variables: { -        unbundled_build: { -            // Unbundled apps will use the prebuilt one -            // prebuilts/sdk/system_current -            enabled: false, -        }, -    },      compile_dex: true,  } diff --git a/test-mock/Android.mk b/test-mock/Android.mk deleted file mode 100644 index 73a7340826a6..000000000000 --- a/test-mock/Android.mk +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (C) 2008 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. -# - -LOCAL_PATH:= $(call my-dir) - -# Archive a copy of the classes.jar in SDK build. -full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.mock.stubs,,COMMON)/classes.jar -$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar) - -# Check that the android.test.mock.stubs library has not changed -# ============================================================== -ANDROID_TEST_MOCK_API_FILE := $(LOCAL_PATH)/api/android-test-mock-current.txt -ANDROID_TEST_MOCK_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-removed.txt - -# Check that the API we're building hasn't changed from the not-yet-released -# SDK version. -$(eval $(call check-api, \ -    check-android-test-mock-api-current, \ -    $(ANDROID_TEST_MOCK_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE), \ -    $(ANDROID_TEST_MOCK_REMOVED_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_REMOVED_API_FILE), \ -    -error 2 -error 3 -error 4 -error 5 -error 6 \ -    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -    -error 25 -error 26 -error 27, \ -    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock.txt, \ -    check-android-test-mock-api, \ -    $(OUT_DOCS)/android.test.mock.docs-stubs.srcjar \ -    )) - -.PHONY: check-android-test-mock-api -checkapi: check-android-test-mock-api - -.PHONY: update-android-test-mock-api -update-api: update-android-test-mock-api - -update-android-test-mock-api: $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE) | $(ACP) -	@echo Copying current.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_API_FILE) $(ANDROID_TEST_MOCK_API_FILE) -	@echo Copying removed.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_REMOVED_API_FILE) - -# Archive a copy of the classes.jar in SDK build. -full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.mock.stubs-system,,COMMON)/classes.jar -$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs_system.jar) - -# Check that the android.test.mock.stubs-system library has not changed -# ===================================================================== -ANDROID_TEST_MOCK_SYSTEM_API_FILE := $(LOCAL_PATH)/api/android-test-mock-system-current.txt -ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-mock-system-removed.txt - -# Check that the API we're building hasn't changed from the not-yet-released -# SDK version. -$(eval $(call check-api, \ -    check-android-test-mock-system-api-current, \ -    $(ANDROID_TEST_MOCK_SYSTEM_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE), \ -    $(ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE), \ -    -error 2 -error 3 -error 4 -error 5 -error 6 \ -    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -    -error 25 -error 26 -error 27, \ -    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_mock-system.txt, \ -    check-android-test-mock-system-api, \ -    $(OUT_DOCS)/android.test.mock.docs-system-stubs.srcjar \ -    )) - -.PHONY: check-android-test-mock-system-api -checkapi: check-android-test-mock-system-api - -.PHONY: update-android-test-mock-system-api -update-api: update-android-test-mock-system-api - -update-android-test-mock-system-api: $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE) | $(ACP) -	@echo Copying current.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_API_FILE) $(ANDROID_TEST_MOCK_SYSTEM_API_FILE) -	@echo Copying removed.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE) $(ANDROID_TEST_MOCK_SYSTEM_REMOVED_API_FILE) diff --git a/test-mock/api/apicheck_msg_android_test_mock-system.txt b/test-mock/api/apicheck_msg_android_test_mock-system.txt deleted file mode 100644 index 3a97117f3ea1..000000000000 --- a/test-mock/api/apicheck_msg_android_test_mock-system.txt +++ /dev/null @@ -1,17 +0,0 @@ - -****************************** -You have tried to change the API from what has been previously approved. - -To make these errors go away, you have two choices: -   1) You can add "@hide" javadoc comments to the methods, etc. listed in the -      errors above. - -   2) You can update android-test-mock-current.txt by executing the following command: -         make update-android-test-mock-system-api - -      To submit the revised android-test-mock-system-current.txt to the main Android repository, -      you will need approval. -****************************** - - - diff --git a/test-mock/api/apicheck_msg_android_test_mock.txt b/test-mock/api/apicheck_msg_android_test_mock.txt deleted file mode 100644 index e388935bf798..000000000000 --- a/test-mock/api/apicheck_msg_android_test_mock.txt +++ /dev/null @@ -1,17 +0,0 @@ - -****************************** -You have tried to change the API from what has been previously approved. - -To make these errors go away, you have two choices: -   1) You can add "@hide" javadoc comments to the methods, etc. listed in the -      errors above. - -   2) You can update android-test-mock-current.txt by executing the following command: -         make update-android-test-mock-api - -      To submit the revised android-test-mock-current.txt to the main Android repository, -      you will need approval. -****************************** - - - diff --git a/test-mock/api/android-test-mock-current.txt b/test-mock/api/current.txt index f3b253c0f460..f3b253c0f460 100644 --- a/test-mock/api/android-test-mock-current.txt +++ b/test-mock/api/current.txt diff --git a/test-mock/api/android-test-mock-removed.txt b/test-mock/api/removed.txt index bd109a887933..bd109a887933 100644 --- a/test-mock/api/android-test-mock-removed.txt +++ b/test-mock/api/removed.txt diff --git a/test-mock/api/android-test-mock-system-current.txt b/test-mock/api/system-current.txt index 20401a50b6a2..20401a50b6a2 100644 --- a/test-mock/api/android-test-mock-system-current.txt +++ b/test-mock/api/system-current.txt diff --git a/test-mock/api/system-removed.txt b/test-mock/api/system-removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-mock/api/system-removed.txt diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt new file mode 100644 index 000000000000..725ea935896f --- /dev/null +++ b/test-mock/api/test-current.txt @@ -0,0 +1,16 @@ +package android.test.mock { + +  public deprecated class MockPackageManager extends android.content.pm.PackageManager { +    method public java.lang.String getDefaultBrowserPackageNameAsUser(int); +    method public int getInstallReason(java.lang.String, android.os.UserHandle); +    method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int); +    method public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int); +    method public java.lang.String[] getNamesForUids(int[]); +    method public java.lang.String getPermissionControllerPackageName(); +    method public java.lang.String getServicesSystemSharedLibraryPackageName(); +    method public java.lang.String getSharedSystemSharedLibraryPackageName(); +    method public boolean isPermissionReviewModeEnabled(); +  } + +} + diff --git a/test-mock/api/test-removed.txt b/test-mock/api/test-removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-mock/api/test-removed.txt diff --git a/test-runner/Android.bp b/test-runner/Android.bp index 2caa6c45f16b..ea615b920df6 100644 --- a/test-runner/Android.bp +++ b/test-runner/Android.bp @@ -16,23 +16,32 @@  // Build the android.test.runner library  // ===================================== -java_library { +java_sdk_library {      name: "android.test.runner", -    installable: true, -    // Needs to be consistent with the repackaged version of this make target. -    java_version: "1.8",      srcs: ["src/**/*.java"],      errorprone: {          javacflags: ["-Xep:DepAnn:ERROR"],      }, -    sdk_version: "current",      libs: [          "android.test.base", -        "android.test.mock.stubs", +        "android.test.mock", +    ], +    stub_only_libs: [ +        "android.test.base", +        "android.test.mock",      ], +    api_packages: [ +        "android.test", +        "android.test.suitebuilder", +        "junit.runner", +        "junit.textui", +    ], + +    droiddoc_options: ["stubsourceonly"], +    compile_dex: true  }  // Build the android.test.runner-minus-junit library @@ -46,8 +55,8 @@ java_library {      sdk_version: "current",      libs: [ -        "android.test.base", -        "android.test.mock.stubs", +        "android.test.base_static", +        "android.test.mock",          "junit",      ],  } @@ -70,7 +79,7 @@ java_library_static {      sdk_version: "current",      libs: [ -        "android.test.base", +        "android.test.base_static",      ],      jarjar_rules: "jarjar-rules.txt", @@ -78,48 +87,3 @@ java_library_static {      java_version: "1.8",  } -droiddoc { -    name: "android-test-runner-api-stubs-gen-docs", -    srcs: [ -        "src/**/*.java", -    ], -    libs: [ -        "core-oj", -        "core-libart", -        "framework", -        "android.test.base", -        "android.test.mock", -    ], -    custom_template: "droiddoc-templates-sdk", -    installable: false, -    args: "-stubpackages android.test:" + -          "android.test.suitebuilder:" + -          "junit.runner:" + -          "junit.textui -stubsourceonly -nodocs", -    api_tag_name: "ANDROID_TEST_RUNNER", -    api_filename: "android-test-runner-current.txt", -    removed_api_filename: "android-test-runner-removed.txt", -} - -// Build the android.test.runner.stubs library -// ========================================= -java_library_static { -    name: "android.test.runner.stubs", -    srcs: [ -        ":android-test-runner-api-stubs-gen-docs", -    ], -    libs: [ -        "android.test.base.stubs", -        "android.test.mock.stubs", -    ], -    product_variables: { -        pdk: { -            enabled: false, -        }, -        unbundled_build: { -            enabled: false, -        }, -    }, -    sdk_version: "current", -    compile_dex: true, -} diff --git a/test-runner/Android.mk b/test-runner/Android.mk index b70d2498d491..18bde8517351 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -16,49 +16,5 @@  LOCAL_PATH:= $(call my-dir) -# For unbundled build we'll use the prebuilt jar from prebuilts/sdk. -ifeq (,$(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK))) - -ANDROID_TEST_RUNNER_API_FILE := $(LOCAL_PATH)/api/android-test-runner-current.txt -ANDROID_TEST_RUNNER_REMOVED_API_FILE := $(LOCAL_PATH)/api/android-test-runner-removed.txt - -full_classes_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,android.test.runner.stubs,,COMMON)/classes.jar -# Archive a copy of the classes.jar in SDK build. -$(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.runner.stubs.jar) - -# Check that the android.test.runner.stubs library has not changed -# ================================================================ - -# Check that the API we're building hasn't changed from the not-yet-released -# SDK version. -$(eval $(call check-api, \ -    check-android-test-runner-api-current, \ -    $(ANDROID_TEST_RUNNER_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE), \ -    $(ANDROID_TEST_RUNNER_REMOVED_API_FILE), \ -    $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_REMOVED_API_FILE), \ -    -error 2 -error 3 -error 4 -error 5 -error 6 \ -    -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \ -    -error 16 -error 17 -error 18 -error 19 -error 20 -error 21 -error 23 -error 24 \ -    -error 25 -error 26 -error 27, \ -    cat $(LOCAL_PATH)/api/apicheck_msg_android_test_runner.txt, \ -    check-android-test-runner-api, \ -    $(OUT_DOCS)/android-test-runner-api-stubs-gen-docs-stubs.srcjar  \ -    )) - -.PHONY: check-android-test-runner-api -checkapi: check-android-test-runner-api - -.PHONY: update-android-test-runner-api -update-api: update-android-test-runner-api - -update-android-test-runner-api: $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE) | $(ACP) -	@echo Copying current.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_API_FILE) $(ANDROID_TEST_RUNNER_API_FILE) -	@echo Copying removed.txt -	$(hide) $(ACP) $(INTERNAL_PLATFORM_ANDROID_TEST_RUNNER_REMOVED_API_FILE) $(ANDROID_TEST_RUNNER_REMOVED_API_FILE) - -endif  # not TARGET_BUILD_APPS not TARGET_BUILD_PDK=true -  # additionally, build unit tests in a separate .apk  include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/test-runner/api/apicheck_msg_android_test_runner.txt b/test-runner/api/apicheck_msg_android_test_runner.txt deleted file mode 100644 index cf2d15ee1ee1..000000000000 --- a/test-runner/api/apicheck_msg_android_test_runner.txt +++ /dev/null @@ -1,17 +0,0 @@ - -****************************** -You have tried to change the API from what has been previously approved. - -To make these errors go away, you have two choices: -   1) You can add "@hide" javadoc comments to the methods, etc. listed in the -      errors above. - -   2) You can update android-test-runner-current.txt by executing the following command: -         make update-android-test-runner-api - -      To submit the revised android-test-runner-current.txt to the main Android repository, -      you will need approval. -****************************** - - - diff --git a/test-runner/api/android-test-runner-current.txt b/test-runner/api/current.txt index 1170eb53ab7f..1170eb53ab7f 100644 --- a/test-runner/api/android-test-runner-current.txt +++ b/test-runner/api/current.txt diff --git a/test-runner/api/removed.txt b/test-runner/api/removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-runner/api/removed.txt diff --git a/test-runner/api/system-current.txt b/test-runner/api/system-current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-runner/api/system-current.txt diff --git a/test-runner/api/system-removed.txt b/test-runner/api/system-removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-runner/api/system-removed.txt diff --git a/test-runner/api/test-current.txt b/test-runner/api/test-current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-runner/api/test-current.txt diff --git a/test-runner/api/test-removed.txt b/test-runner/api/test-removed.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/test-runner/api/test-removed.txt diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp new file mode 100644 index 000000000000..f07f09da3f03 --- /dev/null +++ b/tests/testables/Android.bp @@ -0,0 +1,32 @@ +// +// Copyright (C) 2017 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. +// + +java_library { + +    name: "testables", +    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_MODULE_TAG +    // LOCAL_MODULE_TAG := tests + +    srcs: ["src/**/*.java"], + +    libs: [ +        "android.test.runner", +        "android.test.mock", +        "android-support-test", +        "mockito-target-inline-minus-junit4", +    ], + +} diff --git a/tests/testables/Android.mk b/tests/testables/Android.mk deleted file mode 100644 index f3cbac05d1cb..000000000000 --- a/tests/testables/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (C) 2017 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. -# - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := testables -LOCAL_MODULE_TAG := tests - -LOCAL_SRC_FILES := $(call all-java-files-under,src) - -LOCAL_JAVA_LIBRARIES := android.test.runner android.test.mock \ -    android-support-test \ -    mockito-target-inline-minus-junit4 - -include $(BUILD_STATIC_JAVA_LIBRARY) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 66c1a3c0ffbc..17847eaa0ca5 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -954,16 +954,15 @@ public class WifiEnterpriseConfig implements Parcelable {       * for Hotspot 2.0 defined matching of AAA server certs per WFA HS2.0 spec, section 7.3.3.2,       * second paragraph.       * -     * From wpa_supplicant documentation: -     * Constraint for server domain name. If set, this FQDN is used as a suffix match requirement +     * <p>From wpa_supplicant documentation: +     * <p>Constraint for server domain name. If set, this FQDN is used as a suffix match requirement       * for the AAAserver certificate in SubjectAltName dNSName element(s). If a matching dNSName is -     * found, this constraint is met. If no dNSName values are present, this constraint is matched -     * against SubjectName CN using same suffix match comparison. -     * Suffix match here means that the host/domain name is compared one label at a time starting +     * found, this constraint is met. +     * <p>Suffix match here means that the host/domain name is compared one label at a time starting       * from the top-level domain and all the labels in domain_suffix_match shall be included in the       * certificate. The certificate may include additional sub-level labels in addition to the       * required labels. -     * For example, domain_suffix_match=example.com would match test.example.com but would not +     * <p>For example, domain_suffix_match=example.com would match test.example.com but would not       * match test-example.com.       * @param domain The domain value       */ |