diff options
36 files changed, 795 insertions, 270 deletions
diff --git a/api/current.txt b/api/current.txt index c3dbee03ecc1..05b2a0c6a4fb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6344,6 +6344,7 @@ package android.app.admin { method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String); method public java.lang.CharSequence getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); + method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getLockTaskFeatures(android.content.ComponentName); method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); @@ -6384,6 +6385,7 @@ package android.app.admin { method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); method public boolean installCaCert(android.content.ComponentName, byte[]); + method public boolean installExistingPackage(android.content.ComponentName, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean); @@ -6434,6 +6436,7 @@ package android.app.admin { method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); method public void setKeyguardDisabledFeatures(android.content.ComponentName, int); method public void setLockTaskFeatures(android.content.ComponentName, int); @@ -6503,6 +6506,8 @@ package android.app.admin { field public static final java.lang.String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall"; field public static final java.lang.String DELEGATION_CERT_INSTALL = "delegation-cert-install"; field public static final java.lang.String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; + field public static final java.lang.String DELEGATION_INSTALL_EXISTING_PACKAGE = "delegation-install-existing-package"; + field public static final java.lang.String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; field public static final java.lang.String DELEGATION_PACKAGE_ACCESS = "delegation-package-access"; field public static final java.lang.String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant"; field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 @@ -7006,11 +7011,14 @@ package android.app.slice { field public static final java.lang.String HINT_LARGE = "large"; field public static final java.lang.String HINT_LIST = "list"; field public static final java.lang.String HINT_LIST_ITEM = "list_item"; + field public static final java.lang.String HINT_MAX = "max"; field public static final java.lang.String HINT_NO_TINT = "no_tint"; field public static final java.lang.String HINT_PARTIAL = "partial"; field public static final java.lang.String HINT_SELECTED = "selected"; field public static final java.lang.String HINT_TITLE = "title"; + field public static final java.lang.String SUBTYPE_COLOR = "color"; field public static final java.lang.String SUBTYPE_MESSAGE = "message"; + field public static final java.lang.String SUBTYPE_SLIDER = "slider"; field public static final java.lang.String SUBTYPE_SOURCE = "source"; } @@ -7019,12 +7027,14 @@ package android.app.slice { ctor public Slice.Builder(android.app.slice.Slice.Builder); method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice); method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String); - method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...); - method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>); + method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...); + method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addHints(java.lang.String...); method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...); method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.util.List<java.lang.String>); + method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.lang.String...); + method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.util.List<java.lang.String>); method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.lang.String...); method public android.app.slice.Slice.Builder addSubSlice(android.app.slice.Slice); @@ -7040,10 +7050,11 @@ package android.app.slice { public final class SliceItem implements android.os.Parcelable { method public int describeContents(); method public android.app.PendingIntent getAction(); - method public int getColor(); + method public deprecated int getColor(); method public java.lang.String getFormat(); method public java.util.List<java.lang.String> getHints(); method public android.graphics.drawable.Icon getIcon(); + method public int getInt(); method public android.app.RemoteInput getRemoteInput(); method public android.app.slice.Slice getSlice(); method public java.lang.String getSubType(); @@ -7053,8 +7064,9 @@ package android.app.slice { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.slice.SliceItem> CREATOR; field public static final java.lang.String FORMAT_ACTION = "action"; - field public static final java.lang.String FORMAT_COLOR = "color"; + field public static final deprecated java.lang.String FORMAT_COLOR = "color"; field public static final java.lang.String FORMAT_IMAGE = "image"; + field public static final java.lang.String FORMAT_INT = "int"; field public static final java.lang.String FORMAT_REMOTE_INPUT = "input"; field public static final java.lang.String FORMAT_SLICE = "slice"; field public static final java.lang.String FORMAT_TEXT = "text"; diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ad219837fdf5..34cd67e455ce 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1321,9 +1321,15 @@ public class DevicePolicyManager { public static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; /** + * Delegation for installing existing packages. This scope grants access to the + * {@link #installExistingPackage} API. + */ + public static final String DELEGATION_INSTALL_EXISTING_PACKAGE = + "delegation-install-existing-package"; + + /** * Delegation of management of uninstalled packages. This scope grants access to the * {@code #setKeepUninstalledPackages} and {@code #getKeepUninstalledPackages} APIs. - * @hide */ public static final String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; @@ -6085,7 +6091,6 @@ public class DevicePolicyManager { * @return List of package names to keep cached. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public @Nullable List<String> getKeepUninstalledPackages(@Nullable ComponentName admin) { throwIfParentInstance("getKeepUninstalledPackages"); @@ -6113,7 +6118,6 @@ public class DevicePolicyManager { * @throws SecurityException if {@code admin} is not a device owner. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public void setKeepUninstalledPackages(@Nullable ComponentName admin, @NonNull List<String> packageNames) { @@ -6591,6 +6595,37 @@ public class DevicePolicyManager { } /** + * Install an existing package that has been installed in another user, or has been kept after + * removal via {@link #setKeepUninstalledPackages}. + * This function can be called by a device owner, profile owner or a delegate given + * the {@link #DELEGATION_INSTALL_EXISTING_PACKAGE} scope via {@link #setDelegatedScopes}. + * When called in a secondary user or managed profile, the user/profile must be affiliated with + * the device owner. See {@link #setAffiliationIds}. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package to be installed in the calling profile. + * @return {@code true} if the app is installed; {@code false} otherwise. + * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of + * an affiliated user or profile. + * @see #setKeepUninstalledPackages + * @see #setDelegatedScopes + * @see #setAffiliationIds + * @see #DELEGATION_PACKAGE_ACCESS + */ + public boolean installExistingPackage(@NonNull ComponentName admin, String packageName) { + throwIfParentInstance("installExistingPackage"); + if (mService != null) { + try { + return mService.installExistingPackage(admin, mContext.getPackageName(), + packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + + /** * Called by a device owner or profile owner to disable account management for a specific type * of account. * <p> diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index ff869d247d9a..81da197f2129 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -223,6 +223,7 @@ interface IDevicePolicyManager { void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); + boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); String[] getAccountTypesWithManagementDisabled(); diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java index 807c47d311ff..9b3b4624f42e 100644 --- a/core/java/android/app/slice/Slice.java +++ b/core/java/android/app/slice/Slice.java @@ -143,6 +143,11 @@ public final class Slice implements Parcelable { * OS and should not be cached by apps. */ public static final String HINT_PARTIAL = "partial"; + /** + * A hint representing that this item is the max value possible for the slice containing this. + * Used to indicate the maximum integer value for a {@link #SUBTYPE_SLIDER}. + */ + public static final String HINT_MAX = "max"; /** * Key to retrieve an extra added to an intent when a control is changed. @@ -158,6 +163,14 @@ public final class Slice implements Parcelable { * Subtype to tag the source (i.e. sender) of a {@link #SUBTYPE_MESSAGE}. */ public static final String SUBTYPE_SOURCE = "source"; + /** + * Subtype to tag an item as representing a color. + */ + public static final String SUBTYPE_COLOR = "color"; + /** + * Subtype to tag an item represents a slider. + */ + public static final String SUBTYPE_SLIDER = "slider"; private final SliceItem[] mItems; private final @SliceHint String[] mHints; @@ -389,9 +402,10 @@ public final class Slice implements Parcelable { * Add a color to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} + * @deprecated will be removed once supportlib updates */ public Builder addColor(int color, @Nullable String subType, @SliceHint String... hints) { - mItems.add(new SliceItem(color, SliceItem.FORMAT_COLOR, subType, hints)); + mItems.add(new SliceItem(color, SliceItem.FORMAT_INT, subType, hints)); return this; } @@ -399,6 +413,7 @@ public final class Slice implements Parcelable { * Add a color to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} + * @deprecated will be removed once supportlib updates */ public Builder addColor(int color, @Nullable String subType, @SliceHint List<String> hints) { @@ -406,6 +421,26 @@ public final class Slice implements Parcelable { } /** + * Add a color to the slice being constructed + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) { + mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints)); + return this; + } + + /** + * Add a color to the slice being constructed + * @param subType Optional template-specific type information + * @see {@link SliceItem#getSubType()} + */ + public Builder addInt(int value, @Nullable String subType, + @SliceHint List<String> hints) { + return addInt(value, subType, hints.toArray(new String[hints.size()])); + } + + /** * Add a timestamp to the slice being constructed * @param subType Optional template-specific type information * @see {@link SliceItem#getSubType()} diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java index 743d6b7945e5..5d04c3e813b1 100644 --- a/core/java/android/app/slice/SliceItem.java +++ b/core/java/android/app/slice/SliceItem.java @@ -44,7 +44,7 @@ import java.util.List; * <li>{@link #FORMAT_TEXT}</li> * <li>{@link #FORMAT_IMAGE}</li> * <li>{@link #FORMAT_ACTION}</li> - * <li>{@link #FORMAT_COLOR}</li> + * <li>{@link #FORMAT_INT}</li> * <li>{@link #FORMAT_TIMESTAMP}</li> * <li>{@link #FORMAT_REMOTE_INPUT}</li> * @@ -62,7 +62,7 @@ public final class SliceItem implements Parcelable { FORMAT_TEXT, FORMAT_IMAGE, FORMAT_ACTION, - FORMAT_COLOR, + FORMAT_INT, FORMAT_TIMESTAMP, FORMAT_REMOTE_INPUT, }) @@ -89,7 +89,12 @@ public final class SliceItem implements Parcelable { */ public static final String FORMAT_ACTION = "action"; /** - * A {@link SliceItem} that contains a Color int. + * A {@link SliceItem} that contains an int. + */ + public static final String FORMAT_INT = "int"; + /** + * A {@link SliceItem} that contains an int. + * @deprecated to be removed */ public static final String FORMAT_COLOR = "color"; /** @@ -159,7 +164,7 @@ public final class SliceItem implements Parcelable { * <li>{@link #FORMAT_TEXT}</li> * <li>{@link #FORMAT_IMAGE}</li> * <li>{@link #FORMAT_ACTION}</li> - * <li>{@link #FORMAT_COLOR}</li> + * <li>{@link #FORMAT_INT}</li> * <li>{@link #FORMAT_TIMESTAMP}</li> * <li>{@link #FORMAT_REMOTE_INPUT}</li> * @see #getSubType() () @@ -216,7 +221,14 @@ public final class SliceItem implements Parcelable { } /** - * @return The color held by this {@link #FORMAT_COLOR} SliceItem + * @return The color held by this {@link #FORMAT_INT} SliceItem + */ + public int getInt() { + return (Integer) mObj; + } + + /** + * @deprecated to be removed. */ public int getColor() { return (Integer) mObj; @@ -318,7 +330,7 @@ public final class SliceItem implements Parcelable { case FORMAT_TEXT: TextUtils.writeToParcel((CharSequence) obj, dest, flags); break; - case FORMAT_COLOR: + case FORMAT_INT: dest.writeInt((Integer) obj); break; case FORMAT_TIMESTAMP: @@ -339,7 +351,7 @@ public final class SliceItem implements Parcelable { return new Pair<>( PendingIntent.CREATOR.createFromParcel(in), Slice.CREATOR.createFromParcel(in)); - case FORMAT_COLOR: + case FORMAT_INT: return in.readInt(); case FORMAT_TIMESTAMP: return in.readLong(); diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 0c893b0ff06a..5a91e94781d7 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -16,10 +16,14 @@ package android.content.pm; +import android.annotation.IntDef; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Overall information about the contents of a package. This corresponds * to all of the information collected from AndroidManifest.xml. @@ -330,8 +334,29 @@ public class PackageInfo implements Parcelable { /** @hide */ public int overlayPriority; - /** @hide */ - public boolean isStaticOverlay; + /** + * Flag for use with {@link #mOverlayFlags}. Marks the overlay as static, meaning it cannot + * be enabled/disabled at runtime. + */ + static final int FLAG_OVERLAY_STATIC = 1 << 1; + + /** + * Flag for use with {@link #mOverlayFlags}. Marks the overlay as trusted (not 3rd party). + */ + static final int FLAG_OVERLAY_TRUSTED = 1 << 2; + + @IntDef(flag = true, prefix = "FLAG_OVERLAY_", value = { + FLAG_OVERLAY_STATIC, + FLAG_OVERLAY_TRUSTED + }) + @Retention(RetentionPolicy.SOURCE) + @interface OverlayFlags {} + + /** + * Modifiers that affect the state of this overlay. See {@link #FLAG_OVERLAY_STATIC}, + * {@link #FLAG_OVERLAY_TRUSTED}. + */ + @OverlayFlags int mOverlayFlags; /** * The user-visible SDK version (ex. 26) of the framework against which the application claims @@ -359,6 +384,23 @@ public class PackageInfo implements Parcelable { public PackageInfo() { } + /** + * Returns true if the package is a valid Runtime Overlay package. + * @hide + */ + public boolean isOverlayPackage() { + return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_TRUSTED) != 0; + } + + /** + * Returns true if the package is a valid static Runtime Overlay package. Static overlays + * are not updatable outside of a system update and are safe to load in the system process. + * @hide + */ + public boolean isStaticOverlayPackage() { + return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_STATIC) != 0; + } + @Override public String toString() { return "PackageInfo{" @@ -410,8 +452,8 @@ public class PackageInfo implements Parcelable { dest.writeString(restrictedAccountType); dest.writeString(requiredAccountType); dest.writeString(overlayTarget); - dest.writeInt(isStaticOverlay ? 1 : 0); dest.writeInt(overlayPriority); + dest.writeInt(mOverlayFlags); dest.writeInt(compileSdkVersion); dest.writeString(compileSdkVersionCodename); } @@ -465,8 +507,8 @@ public class PackageInfo implements Parcelable { restrictedAccountType = source.readString(); requiredAccountType = source.readString(); overlayTarget = source.readString(); - isStaticOverlay = source.readInt() != 0; overlayPriority = source.readInt(); + mOverlayFlags = source.readInt(); compileSdkVersion = source.readInt(); compileSdkVersionCodename = source.readString(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 153c944a8d93..fb1b885f0106 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -689,7 +689,15 @@ public class PackageParser { pi.requiredAccountType = p.mRequiredAccountType; pi.overlayTarget = p.mOverlayTarget; pi.overlayPriority = p.mOverlayPriority; - pi.isStaticOverlay = p.mIsStaticOverlay; + + if (p.mIsStaticOverlay) { + pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC; + } + + if (p.mTrustedOverlay) { + pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED; + } + pi.compileSdkVersion = p.mCompileSdkVersion; pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename; pi.firstInstallTime = firstInstallTime; diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index b31c7bcdb31e..1d66dc6d939f 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -342,7 +342,17 @@ public final class ContextHubManager { @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<Void> loadNanoApp( ContextHubInfo hubInfo, NanoAppBinary appBinary) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<Void> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP); + IContextHubTransactionCallback callback = createTransactionCallback(transaction); + + try { + mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** @@ -357,7 +367,17 @@ public final class ContextHubManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<Void> unloadNanoApp(ContextHubInfo hubInfo, long nanoAppId) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<Void> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP); + IContextHubTransactionCallback callback = createTransactionCallback(transaction); + + try { + mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** @@ -401,7 +421,17 @@ public final class ContextHubManager { */ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public ContextHubTransaction<List<NanoAppState>> queryNanoApps(ContextHubInfo hubInfo) { - throw new UnsupportedOperationException("TODO: Implement this"); + ContextHubTransaction<List<NanoAppState>> transaction = + new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS); + IContextHubTransactionCallback callback = createQueryCallback(transaction); + + try { + mService.queryNanoApps(hubInfo.getId(), callback); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + return transaction; } /** diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java index a8569ef479a1..b808de3a11d6 100644 --- a/core/java/android/hardware/location/ContextHubTransaction.java +++ b/core/java/android/hardware/location/ContextHubTransaction.java @@ -72,7 +72,8 @@ public class ContextHubTransaction<T> { TRANSACTION_FAILED_PENDING, TRANSACTION_FAILED_AT_HUB, TRANSACTION_FAILED_TIMEOUT, - TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE}) + TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE, + TRANSACTION_FAILED_HAL_UNAVAILABLE}) public @interface Result {} public static final int TRANSACTION_SUCCESS = 0; /** @@ -103,6 +104,10 @@ public class ContextHubTransaction<T> { * Failure mode when the transaction has failed internally at the service. */ public static final int TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE = 7; + /** + * Failure mode when the Context Hub HAL was not available. + */ + public static final int TRANSACTION_FAILED_HAL_UNAVAILABLE = 8; /** * A class describing the response for a ContextHubTransaction. @@ -189,6 +194,30 @@ public class ContextHubTransaction<T> { } /** + * Converts a transaction type to a human-readable string + * + * @param type the type of a transaction + * @param upperCase {@code true} if upper case the first letter, {@code false} otherwise + * @return a string describing the transaction + */ + public static String typeToString(@Type int type, boolean upperCase) { + switch (type) { + case ContextHubTransaction.TYPE_LOAD_NANOAPP: + return upperCase ? "Load" : "load"; + case ContextHubTransaction.TYPE_UNLOAD_NANOAPP: + return upperCase ? "Unload" : "unload"; + case ContextHubTransaction.TYPE_ENABLE_NANOAPP: + return upperCase ? "Enable" : "enable"; + case ContextHubTransaction.TYPE_DISABLE_NANOAPP: + return upperCase ? "Disable" : "disable"; + case ContextHubTransaction.TYPE_QUERY_NANOAPPS: + return upperCase ? "Query" : "query"; + default: + return upperCase ? "Unknown" : "unknown"; + } + } + + /** * @return the type of the transaction */ @Type @@ -239,7 +268,7 @@ public class ContextHubTransaction<T> { * A transaction can be invalidated if the process owning the transaction is no longer active * and the reference to this object is lost. * - * This method or {@link #setCallbackOnCompletecan(ContextHubTransaction.Callback)} can only be + * This method or {@link #setCallbackOnComplete(ContextHubTransaction.Callback)} can only be * invoked once, or an IllegalStateException will be thrown. * * @param callback the callback to be invoked upon completion diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 1bb7c8fbb6e7..628ebc7d4579 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -20,41 +20,56 @@ package android.hardware.location; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; import android.hardware.location.NanoApp; +import android.hardware.location.NanoAppBinary; import android.hardware.location.NanoAppFilter; import android.hardware.location.NanoAppInstanceInfo; import android.hardware.location.IContextHubCallback; import android.hardware.location.IContextHubClient; import android.hardware.location.IContextHubClientCallback; +import android.hardware.location.IContextHubTransactionCallback; /** * @hide */ interface IContextHubService { - // register a callback to receive messages + // Registers a callback to receive messages int registerCallback(in IContextHubCallback callback); // Gets a list of available context hub handles int[] getContextHubHandles(); - // Get the properties of a hub + // Gets the properties of a hub ContextHubInfo getContextHubInfo(int contextHubHandle); - // Load a nanoapp on a specified context hub + // Loads a nanoapp at the specified hub (old API) int loadNanoApp(int hubHandle, in NanoApp app); - // Unload a nanoapp instance + // Unloads a nanoapp given its instance ID (old API) int unloadNanoApp(int nanoAppInstanceHandle); - // get information about a nanoAppInstance + // Gets the NanoAppInstanceInfo of a nanoapp give its instance ID NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle); - // find all nanoApp instances matching some filter + // Finds all nanoApp instances matching some filter int[] findNanoAppOnHub(int hubHandle, in NanoAppFilter filter); - // send a message to a nanoApp + // Sends a message to a nanoApp int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg); // Creates a client to send and receive messages IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId); + + // Loads a nanoapp at the specified hub (new API) + void loadNanoAppOnHub( + int contextHubId, in IContextHubTransactionCallback transactionCallback, + in NanoAppBinary nanoAppBinary); + + // Unloads a nanoapp on a specified context hub (new API) + void unloadNanoAppFromHub( + int contextHubId, in IContextHubTransactionCallback transactionCallback, + long nanoAppId); + + // Queries for a list of nanoapps + void queryNanoApps(int contextHubId, in IContextHubTransactionCallback transactionCallback); } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 400b075d889d..53ddd1699d68 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -887,6 +887,7 @@ public class StaticLayout extends Layout { if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { + measured = MeasuredText.buildForBidi(source, bufEnd, bufEnd, textDir, measured); paint.getFontMetricsInt(fm); v = out(source, bufEnd, bufEnd, fm.ascent, fm.descent, @@ -894,7 +895,7 @@ public class StaticLayout extends Layout { v, spacingmult, spacingadd, null, null, fm, 0, - needMultiply, null, bufEnd, + needMultiply, measured, bufEnd, includepad, trackpad, addLastLineSpacing, null, null, bufStart, ellipsize, ellipsizedWidth, 0, paint, false); @@ -912,7 +913,7 @@ public class StaticLayout extends Layout { private int out(final CharSequence text, final int start, final int end, int above, int below, int top, int bottom, int v, final float spacingmult, final float spacingadd, final LineHeightSpan[] chooseHt, final int[] chooseHtv, final Paint.FontMetricsInt fm, - final int flags, final boolean needMultiply, @Nullable final MeasuredText measured, + final int flags, final boolean needMultiply, @NonNull final MeasuredText measured, final int bufEnd, final boolean includePad, final boolean trackPad, final boolean addLastLineLineSpacing, final char[] chs, final float[] widths, final int widthStart, final TextUtils.TruncateAt ellipsize, final float ellipsisWidth, @@ -921,7 +922,7 @@ public class StaticLayout extends Layout { final int off = j * mColumns; final int want = off + mColumns + TOP; int[] lines = mLines; - final int dir = (start == end) ? Layout.DIR_LEFT_TO_RIGHT : measured.getParagraphDir(); + final int dir = measured.getParagraphDir(); if (want >= lines.length) { final int[] grow = ArrayUtils.newUnpaddedIntArray(GrowingArrayUtils.growSize(want)); @@ -948,11 +949,7 @@ public class StaticLayout extends Layout { lines[off + TAB] |= flags & TAB_MASK; lines[off + HYPHEN] = flags; lines[off + DIR] |= dir << DIR_SHIFT; - if (start == end) { - mLineDirections[j] = Layout.DIRS_ALL_LEFT_TO_RIGHT; - } else { - mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart); - } + mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart); final boolean firstLine = (j == 0); final boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 6d4998b05c48..129a255c1989 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -142,10 +142,11 @@ public final class ViewRootImpl implements ViewParent, private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV; /** - * Set to false if we do not want to use the multi threaded renderer. Note that by disabling + * Set to false if we do not want to use the multi threaded renderer even though + * threaded renderer (aka hardware renderering) is used. Note that by disabling * this, WindowCallbacks will not fire. */ - private static final boolean USE_MT_RENDERER = true; + private static final boolean MT_RENDERER_AVAILABLE = true; /** * Set this system property to true to force the view hierarchy to render @@ -302,6 +303,7 @@ public final class ViewRootImpl implements ViewParent, Rect mDirty; public boolean mIsAnimating; + private boolean mUseMTRenderer; private boolean mDragResizing; private boolean mInvalidateRootRequested; private int mResizeMode; @@ -548,18 +550,14 @@ public final class ViewRootImpl implements ViewParent, } public void addWindowCallbacks(WindowCallbacks callback) { - if (USE_MT_RENDERER) { - synchronized (mWindowCallbacks) { - mWindowCallbacks.add(callback); - } + synchronized (mWindowCallbacks) { + mWindowCallbacks.add(callback); } } public void removeWindowCallbacks(WindowCallbacks callback) { - if (USE_MT_RENDERER) { - synchronized (mWindowCallbacks) { - mWindowCallbacks.remove(callback); - } + synchronized (mWindowCallbacks) { + mWindowCallbacks.remove(callback); } } @@ -685,7 +683,17 @@ public final class ViewRootImpl implements ViewParent, // If the application owns the surface, don't enable hardware acceleration if (mSurfaceHolder == null) { + // While this is supposed to enable only, it can effectively disable + // the acceleration too. enableHardwareAcceleration(attrs); + final boolean useMTRenderer = MT_RENDERER_AVAILABLE + && mAttachInfo.mThreadedRenderer != null; + if (mUseMTRenderer != useMTRenderer) { + // Shouldn't be resizing, as it's done only in window setup, + // but end just in case. + endDragResizing(); + mUseMTRenderer = useMTRenderer; + } } boolean restore = false; @@ -2088,7 +2096,7 @@ public final class ViewRootImpl implements ViewParent, endDragResizing(); } } - if (!USE_MT_RENDERER) { + if (!mUseMTRenderer) { if (dragResizing) { mCanvasOffsetX = mWinFrame.left; mCanvasOffsetY = mWinFrame.top; @@ -2726,8 +2734,10 @@ public final class ViewRootImpl implements ViewParent, @Override public void onPostDraw(DisplayListCanvas canvas) { drawAccessibilityFocusedDrawableIfNeeded(canvas); - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onPostDraw(canvas); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onPostDraw(canvas); + } } } @@ -3058,7 +3068,8 @@ public final class ViewRootImpl implements ViewParent, return; } - if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) { + if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, + scalingRequired, dirty, surfaceInsets)) { return; } } @@ -3074,11 +3085,22 @@ public final class ViewRootImpl implements ViewParent, * @return true if drawing was successful, false if an error occurred */ private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, - boolean scalingRequired, Rect dirty) { + boolean scalingRequired, Rect dirty, Rect surfaceInsets) { // Draw with software renderer. final Canvas canvas; + + // We already have the offset of surfaceInsets in xoff, yoff and dirty region, + // therefore we need to add it back when moving the dirty region. + int dirtyXOffset = xoff; + int dirtyYOffset = yoff; + if (surfaceInsets != null) { + dirtyXOffset += surfaceInsets.left; + dirtyYOffset += surfaceInsets.top; + } + try { + dirty.offset(-dirtyXOffset, -dirtyYOffset); final int left = dirty.left; final int top = dirty.top; final int right = dirty.right; @@ -3105,6 +3127,8 @@ public final class ViewRootImpl implements ViewParent, // kill stuff (or ourself) for no reason. mLayoutRequested = true; // ask wm for a new surface next time. return false; + } finally { + dirty.offset(dirtyXOffset, dirtyYOffset); // Reset to the original value. } try { @@ -6578,7 +6602,7 @@ public final class ViewRootImpl implements ViewParent, // Tell all listeners that we are resizing the window so that the chrome can get // updated as fast as possible on a separate thread, - if (mDragResizing) { + if (mDragResizing && mUseMTRenderer) { boolean fullscreen = frame.equals(backDropFrame); synchronized (mWindowCallbacks) { for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { @@ -7828,9 +7852,11 @@ public final class ViewRootImpl implements ViewParent, Rect stableInsets, int resizeMode) { if (!mDragResizing) { mDragResizing = true; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen, - systemInsets, stableInsets, resizeMode); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onWindowDragResizeStart( + initialBounds, fullscreen, systemInsets, stableInsets, resizeMode); + } } mFullRedrawNeeded = true; } @@ -7842,8 +7868,10 @@ public final class ViewRootImpl implements ViewParent, private void endDragResizing() { if (mDragResizing) { mDragResizing = false; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - mWindowCallbacks.get(i).onWindowDragResizeEnd(); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + mWindowCallbacks.get(i).onWindowDragResizeEnd(); + } } mFullRedrawNeeded = true; } @@ -7851,19 +7879,21 @@ public final class ViewRootImpl implements ViewParent, private boolean updateContentDrawBounds() { boolean updated = false; - for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { - updated |= mWindowCallbacks.get(i).onContentDrawn( - mWindowAttributes.surfaceInsets.left, - mWindowAttributes.surfaceInsets.top, - mWidth, mHeight); + if (mUseMTRenderer) { + for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { + updated |= + mWindowCallbacks.get(i).onContentDrawn(mWindowAttributes.surfaceInsets.left, + mWindowAttributes.surfaceInsets.top, mWidth, mHeight); + } } return updated | (mDragResizing && mReportNextDraw); } private void requestDrawWindow() { - if (mReportNextDraw) { - mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size()); + if (!mUseMTRenderer) { + return; } + mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size()); for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw); } diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java index 6a0edef49643..82affe2f86b1 100644 --- a/core/java/com/android/internal/widget/ButtonBarLayout.java +++ b/core/java/com/android/internal/widget/ButtonBarLayout.java @@ -151,7 +151,7 @@ public class ButtonBarLayout extends LinearLayout { private void setStacked(boolean stacked) { setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL); - setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM); + setGravity(stacked ? Gravity.END : Gravity.BOTTOM); final View spacer = findViewById(R.id.spacer); if (spacer != null) { diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp index 460a0d75ca4e..564afeb39490 100644 --- a/core/jni/android/graphics/NinePatch.cpp +++ b/core/jni/android/graphics/NinePatch.cpp @@ -101,7 +101,8 @@ public: SkIRect src = SkIRect::MakeWH(bitmap.width(), bitmap.height()); lattice.fBounds = &src; NinePatchUtils::SetLatticeDivs(&lattice, *chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; SkRegion* region = nullptr; if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) { diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index d3da21b5635b..b9ff0a787931 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -747,7 +747,7 @@ static long long get_zram_mem_used() static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out) { - char buffer[1024]; + char buffer[4096]; size_t numFound = 0; if (out == NULL) { diff --git a/libs/hwui/NinePatchUtils.h b/libs/hwui/NinePatchUtils.h index 8f866f50e450..db9509fff378 100644 --- a/libs/hwui/NinePatchUtils.h +++ b/libs/hwui/NinePatchUtils.h @@ -53,10 +53,13 @@ static inline int NumDistinctRects(const SkCanvas::Lattice& lattice) { return xRects * yRects; } -static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice::Flags* flags, - int numFlags, const Res_png_9patch& chunk) { - lattice->fFlags = flags; - sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::Flags)); +static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, + SkCanvas::Lattice::RectType* flags, int numFlags, const Res_png_9patch& chunk, + SkColor* colors) { + lattice->fRectTypes = flags; + lattice->fColors = colors; + sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::RectType)); + sk_bzero(colors, numFlags * sizeof(SkColor)); bool needPadRow = lattice->fYCount > 0 && 0 == lattice->fYDivs[0]; bool needPadCol = lattice->fXCount > 0 && 0 == lattice->fXDivs[0]; @@ -65,6 +68,7 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice if (needPadRow) { // Skip flags for the degenerate first row of rects. flags += lattice->fXCount + 1; + colors += lattice->fXCount + 1; yCount--; } @@ -75,20 +79,28 @@ static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice if (0 == x && needPadCol) { // First rect of each column is degenerate, skip the flag. flags++; + colors++; continue; } - if (0 == chunk.getColors()[i++]) { - *flags = SkCanvas::Lattice::kTransparent_Flags; + uint32_t currentColor = chunk.getColors()[i++]; + if (Res_png_9patch::TRANSPARENT_COLOR == currentColor) { + *flags = SkCanvas::Lattice::kTransparent; + setFlags = true; + } else if (Res_png_9patch::NO_COLOR != currentColor) { + *flags = SkCanvas::Lattice::kFixedColor; + *colors = currentColor; setFlags = true; } flags++; + colors++; } } if (!setFlags) { - lattice->fFlags = nullptr; + lattice->fRectTypes = nullptr; + lattice->fColors = nullptr; } } diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index eb0d161d71d1..13e1ebec943e 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -699,7 +699,8 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa SkCanvas::Lattice lattice; NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; int numFlags = 0; if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) { // We can expect the framework to give us a color for every distinct rect. @@ -707,9 +708,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1); } - SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags); + SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags); + SkAutoSTMalloc<25, SkColor> colors(numFlags); if (numFlags > 0) { - NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk); + NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get()); } lattice.fBounds = nullptr; diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp index 288d0395370c..107890e57a19 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp @@ -45,8 +45,7 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface()); LOG_ALWAYS_FATAL_IF(!glInterface.get()); - grContext.reset(GrContext::Create(GrBackend::kOpenGL_GrBackend, - (GrBackendContext)glInterface.get())); + grContext = GrContext::MakeGL(std::move(glInterface)); } else { grContext->resetContext(); } diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp index 91b35c281b04..035cea3f61b0 100644 --- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp +++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp @@ -218,7 +218,8 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch SkCanvas::Lattice lattice; NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height()); - lattice.fFlags = nullptr; + lattice.fRectTypes = nullptr; + lattice.fColors = nullptr; int numFlags = 0; if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) { // We can expect the framework to give us a color for every distinct rect. @@ -226,9 +227,10 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1); } - SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags); + SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags); + SkAutoSTMalloc<25, SkColor> colors(numFlags); if (numFlags > 0) { - NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk); + NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get()); } lattice.fBounds = nullptr; diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp index 5e89faec1bab..907f2d2d398f 100644 --- a/libs/hwui/renderthread/CacheManager.cpp +++ b/libs/hwui/renderthread/CacheManager.cpp @@ -53,13 +53,13 @@ CacheManager::CacheManager(const DisplayInfo& display) : mMaxSurfaceArea(display } } -void CacheManager::reset(GrContext* context) { - if (context != mGrContext.get()) { +void CacheManager::reset(sk_sp<GrContext> context) { + if (context != mGrContext) { destroy(); } if (context) { - mGrContext = sk_ref_sp(context); + mGrContext = std::move(context); mGrContext->getResourceCacheLimits(&mMaxResources, nullptr); updateContextCacheSizes(); } diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h index d0370453c258..7d733525194f 100644 --- a/libs/hwui/renderthread/CacheManager.h +++ b/libs/hwui/renderthread/CacheManager.h @@ -61,7 +61,7 @@ private: CacheManager(const DisplayInfo& display); - void reset(GrContext* grContext); + void reset(sk_sp<GrContext> grContext); void destroy(); void updateContextCacheSizes(); diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 4df7cafa4792..848c6a81d2b7 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -141,8 +141,9 @@ void EglManager::initialize() { GrContextOptions options; options.fDisableDistanceFieldPaths = true; mRenderThread.cacheManager().configureContext(&options); - mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend, - (GrBackendContext)glInterface.get(), options)); + sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options)); + LOG_ALWAYS_FATAL_IF(!grContext.get()); + mRenderThread.setGrContext(grContext); } } diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 20443ec38c90..79dc09ffbf1d 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -173,12 +173,12 @@ Readback& RenderThread::readback() { return *mReadback; } -void RenderThread::setGrContext(GrContext* context) { +void RenderThread::setGrContext(sk_sp<GrContext> context) { mCacheManager->reset(context); - if (mGrContext.get()) { + if (mGrContext) { mGrContext->releaseResourcesAndAbandonContext(); } - mGrContext.reset(context); + mGrContext = std::move(context); } int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 970537b69fad..3aa548773b3b 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -88,7 +88,7 @@ public: const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; } GrContext* getGrContext() const { return mGrContext.get(); } - void setGrContext(GrContext* cxt); + void setGrContext(sk_sp<GrContext> cxt); CacheManager& cacheManager() { return *mCacheManager; } VulkanManager& vulkanManager() { return *mVkManager; } diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index a693e68afd66..9d246ffc9a4a 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -58,6 +58,7 @@ void VulkanManager::initialize() { mBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr, &mPresentQueueIndex, canPresent)); + LOG_ALWAYS_FATAL_IF(!mBackendContext.get()); // Get all the addresses of needed vulkan functions VkInstance instance = mBackendContext->fInstance; @@ -110,8 +111,9 @@ void VulkanManager::initialize() { GrContextOptions options; options.fDisableDistanceFieldPaths = true; mRenderThread.cacheManager().configureContext(&options); - mRenderThread.setGrContext( - GrContext::Create(kVulkan_GrBackend, (GrBackendContext)mBackendContext.get(), options)); + sk_sp<GrContext> grContext(GrContext::MakeVulkan(mBackendContext, options)); + LOG_ALWAYS_FATAL_IF(!grContext.get()); + mRenderThread.setGrContext(grContext); DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize()); if (Properties::enablePartialUpdates && Properties::useBufferAge) { diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index f5637944e72e..bab1e5e4698f 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -32,6 +32,7 @@ android:id="@+id/volume_dialog_content" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_toStartOf="@id/expand" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical" > @@ -44,54 +45,83 @@ <!-- volume rows added and removed here! :-) --> </LinearLayout> - <!-- special row for ringer mode --> - <RelativeLayout - android:id="@+id/ringer_mode" - android:layout_width="match_parent" + + </LinearLayout> + <LinearLayout + android:id="@+id/expand" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_alignParentEnd="true" + android:layout_alignParentTop="true" + android:layout_marginEnd="@dimen/volume_expander_margin_end" > + <TextView + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/rounded_bg_full" - android:clipChildren="false" - android:clipToPadding="false" - android:layout_margin="10dp"> + android:ellipsize="end" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.Volume.Header" /> + <com.android.keyguard.AlphaOptimizedImageButton + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/volume_expand_button" + style="@style/VolumeButtons" + android:layout_width="@dimen/volume_button_size" + android:layout_height="@dimen/volume_button_size" + android:clickable="true" + android:soundEffectsEnabled="false" + android:src="@drawable/ic_volume_collapse_animation" + android:background="@drawable/ripple_drawable" + tools:ignore="RtlHardcoded" /> + </LinearLayout> + <!-- special row for ringer mode --> + <RelativeLayout + android:id="@+id/ringer_mode" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/rounded_bg_full" + android:clipChildren="false" + android:clipToPadding="false" + android:layout_below="@id/volume_dialog_content" + android:layout_margin="10dp"> - <com.android.keyguard.AlphaOptimizedImageButton - android:id="@+id/ringer_icon" - style="@style/VolumeButtons" - android:background="?android:selectableItemBackgroundBorderless" - android:layout_width="@dimen/volume_button_size" - android:layout_height="@dimen/volume_button_size" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:soundEffectsEnabled="false" /> + <com.android.keyguard.AlphaOptimizedImageButton + android:id="@+id/ringer_icon" + style="@style/VolumeButtons" + android:background="?android:selectableItemBackgroundBorderless" + android:layout_width="@dimen/volume_button_size" + android:layout_height="@dimen/volume_button_size" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:soundEffectsEnabled="false" /> - <TextView - android:id="@+id/ringer_title" - android:text="@string/stream_ring" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:maxLines="1" - android:layout_alignParentStart="true" - android:layout_centerVertical="true" - android:layout_toEndOf="@+id/ringer_icon" - android:layout_marginStart="64dp" - android:textColor="?android:attr/colorControlNormal" - android:textAppearance="?android:attr/textAppearanceSmall" - android:paddingStart="@dimen/volume_row_header_padding_start" /> + <TextView + android:id="@+id/ringer_title" + android:text="@string/stream_ring" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="1" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/ringer_icon" + android:layout_marginStart="64dp" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" + android:paddingStart="@dimen/volume_row_header_padding_start" /> - <TextView - android:id="@+id/ringer_status" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:layout_alignParentEnd="true" - android:layout_centerVertical="true" - android:layout_marginEnd="14dp" - android:maxLines="1" - android:textColor="?android:attr/colorControlNormal" - android:textAppearance="?android:attr/textAppearanceSmall" /> + <TextView + android:id="@+id/ringer_status" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:layout_alignParentEnd="true" + android:layout_centerVertical="true" + android:layout_marginEnd="14dp" + android:maxLines="1" + android:textColor="?android:attr/colorControlNormal" + android:textAppearance="?android:attr/textAppearanceSmall" /> - </RelativeLayout> - </LinearLayout> + </RelativeLayout> </RelativeLayout> </com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 3e70980fdc67..7959b72ce7b3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -29,11 +29,15 @@ import android.app.Dialog; import android.app.KeyguardManager; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; +import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; import android.media.AudioManager; import android.media.AudioSystem; import android.os.Debug; @@ -42,6 +46,8 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.provider.Settings.Global; +import android.transition.AutoTransition; +import android.transition.TransitionManager; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; @@ -66,6 +72,7 @@ import android.widget.TextView; import com.android.settingslib.Utils; import com.android.systemui.Dependency; +import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; @@ -97,7 +104,7 @@ public class VolumeDialogImpl implements VolumeDialog { private CustomDialog mDialog; private ViewGroup mDialogView; private ViewGroup mDialogRowsView; - private ViewGroup mDialogContentView; + private ImageButton mExpandButton; private ImageButton mRingerIcon; private TextView mRingerStatus; private final List<VolumeRow> mRows = new ArrayList<>(); @@ -109,9 +116,10 @@ public class VolumeDialogImpl implements VolumeDialog { private final Accessibility mAccessibility = new Accessibility(); private final ColorStateList mActiveSliderTint; private final ColorStateList mInactiveSliderTint; - private VolumeUiLayout mHardwareLayout; private boolean mShowing; + private boolean mExpanded; + private boolean mExpandButtonAnimationRunning; private boolean mShowA11yStream; private int mActiveStream; @@ -170,57 +178,57 @@ public class VolumeDialogImpl implements VolumeDialog { mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); mDialog.setContentView(R.layout.volume_dialog); - mDialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialog) { - mDialogView.setTranslationY(-mDialogView.getHeight()); - mDialogView.setAlpha(0); - mDialogView.animate() - .alpha(1) - .translationY(0) - .setDuration(300) - .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) - .withEndAction(() -> { - mWindow.getDecorView().requestAccessibilityFocus(); - }) - .start(); - } + mDialog.setOnShowListener(dialog -> { + mDialogView.setTranslationY(-mDialogView.getHeight()); + mDialogView.setAlpha(0); + mDialogView.animate() + .alpha(1) + .translationY(0) + .setDuration(300) + .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) + .withEndAction(() -> { + mWindow.getDecorView().requestAccessibilityFocus(); + }) + .start(); }); mDialogView = mDialog.findViewById(R.id.volume_dialog); - mDialogView.setOnHoverListener(new View.OnHoverListener() { - @Override - public boolean onHover(View v, MotionEvent event) { - int action = event.getActionMasked(); - mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) - || (action == MotionEvent.ACTION_HOVER_MOVE); - rescheduleTimeoutH(); - return true; - } + mDialogView.setOnHoverListener((v, event) -> { + int action = event.getActionMasked(); + mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) + || (action == MotionEvent.ACTION_HOVER_MOVE); + rescheduleTimeoutH(); + return true; }); - mHardwareLayout = VolumeUiLayout.get(mDialogView); - mHardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE)); + VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView); + hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE)); + + ViewGroup dialogContentView = mDialog.findViewById(R.id.volume_dialog_content); + mDialogRowsView = dialogContentView.findViewById(R.id.volume_dialog_rows); + mRingerIcon = mDialog.findViewById(R.id.ringer_icon); + mRingerStatus = mDialog.findViewById(R.id.ringer_status); - mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content); - mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows); - mRingerIcon = mDialogContentView.findViewById(R.id.ringer_icon); - mRingerStatus = mDialogContentView.findViewById(R.id.ringer_status); + mExpanded = false; + mExpandButton = mDialogView.findViewById(R.id.volume_expand_button); + mExpandButton.setOnClickListener(mClickExpand); + mExpandButton.setVisibility( + AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE); if (mRows.isEmpty()) { addRow(AudioManager.STREAM_MUSIC, - R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true); + R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true); if (!AudioSystem.isSingleVolume(mContext)) { addRow(AudioManager.STREAM_RING, - R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, false); + R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false); addRow(AudioManager.STREAM_ALARM, - R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false); + R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false); addRow(AudioManager.STREAM_VOICE_CALL, - R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false); + R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false, false); addRow(AudioManager.STREAM_BLUETOOTH_SCO, - R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false); - addRow(AudioManager.STREAM_SYSTEM, - R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false); + R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false, false); + addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system, + R.drawable.ic_volume_system_mute, false, false); addRow(AudioManager.STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility, - R.drawable.ic_volume_accessibility, true); + R.drawable.ic_volume_accessibility, true, false); } } else { addExistingRows(); @@ -249,14 +257,15 @@ public class VolumeDialogImpl implements VolumeDialog { mHandler.sendEmptyMessage(H.RECHECK_ALL); } - private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) { - addRow(stream, iconRes, iconMuteRes, important, false); + private void addRow(int stream, int iconRes, int iconMuteRes, boolean important, + boolean defaultStream) { + addRow(stream, iconRes, iconMuteRes, important, defaultStream, false); } private void addRow(int stream, int iconRes, int iconMuteRes, boolean important, - boolean dynamic) { + boolean defaultStream, boolean dynamic) { VolumeRow row = new VolumeRow(); - initRow(row, stream, iconRes, iconMuteRes, important); + initRow(row, stream, iconRes, iconMuteRes, important, defaultStream); int rowSize; int viewSize; if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1 @@ -274,7 +283,8 @@ public class VolumeDialogImpl implements VolumeDialog { int N = mRows.size(); for (int i = 0; i < N; i++) { final VolumeRow row = mRows.get(i); - initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important); + initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important, + row.defaultStream); mDialogRowsView.addView(row.view); updateVolumeRowH(row); } @@ -299,6 +309,7 @@ public class VolumeDialogImpl implements VolumeDialog { public void dump(PrintWriter writer) { writer.println(VolumeDialogImpl.class.getSimpleName() + " state:"); writer.print(" mShowing: "); writer.println(mShowing); + writer.print(" mExpanded: "); writer.println(mExpanded); writer.print(" mActiveStream: "); writer.println(mActiveStream); writer.print(" mDynamic: "); writer.println(mDynamic); writer.print(" mAutomute: "); writer.println(mAutomute); @@ -317,11 +328,12 @@ public class VolumeDialogImpl implements VolumeDialog { @SuppressLint("InflateParams") private void initRow(final VolumeRow row, final int stream, int iconRes, int iconMuteRes, - boolean important) { + boolean important, boolean defaultStream) { row.stream = stream; row.iconRes = iconRes; row.iconMuteRes = iconMuteRes; row.important = important; + row.defaultStream = defaultStream; row.view = mDialog.getLayoutInflater().inflate(R.layout.volume_dialog_row, null); row.view.setId(row.stream); row.view.setTag(row); @@ -359,34 +371,31 @@ public class VolumeDialogImpl implements VolumeDialog { row.icon = row.view.findViewById(R.id.volume_row_icon); row.icon.setImageResource(iconRes); if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) { - row.icon.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState); - mController.setActiveStream(row.stream); - if (row.stream == AudioManager.STREAM_RING) { - final boolean hasVibrator = mController.hasVibrator(); - if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) { - if (hasVibrator) { - mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false); - } else { - final boolean wasZero = row.ss.level == 0; - mController.setStreamVolume(stream, - wasZero ? row.lastAudibleLevel : 0); - } + row.icon.setOnClickListener(v -> { + Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState); + mController.setActiveStream(row.stream); + if (row.stream == AudioManager.STREAM_RING) { + final boolean hasVibrator = mController.hasVibrator(); + if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) { + if (hasVibrator) { + mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false); } else { - mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false); - if (row.ss.level == 0) { - mController.setStreamVolume(stream, 1); - } + final boolean wasZero = row.ss.level == 0; + mController.setStreamVolume(stream, + wasZero ? row.lastAudibleLevel : 0); } } else { - final boolean vmute = row.ss.level == row.ss.levelMin; - mController.setStreamVolume(stream, - vmute ? row.lastAudibleLevel : row.ss.levelMin); + mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false); + if (row.ss.level == 0) { + mController.setStreamVolume(stream, 1); + } } - row.userAttempt = 0; // reset the grace period, slider updates immediately + } else { + final boolean vmute = row.ss.level == row.ss.levelMin; + mController.setStreamVolume(stream, + vmute ? row.lastAudibleLevel : row.ss.levelMin); } + row.userAttempt = 0; // reset the grace period, slider updates immediately }); } else { row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); @@ -450,6 +459,7 @@ public class VolumeDialogImpl implements VolumeDialog { private int computeTimeoutH() { if (mAccessibility.mFeedbackEnabled) return 20000; if (mHovering) return 16000; + if (mExpanded) return 5000; if (mSafetyWarning != null) return 5000; return 3000; } @@ -461,6 +471,8 @@ public class VolumeDialogImpl implements VolumeDialog { mDialogView.animate().cancel(); mShowing = false; + updateExpandedH(false /* expanding */, true /* dismissing */); + mDialogView.setTranslationY(0); mDialogView.setAlpha(1); mDialogView.animate() @@ -493,6 +505,76 @@ public class VolumeDialogImpl implements VolumeDialog { } } + private void updateExpandedH(final boolean expanded, final boolean dismissing) { + if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded); + + if (mExpanded == expanded) return; + mExpanded = expanded; + mExpandButtonAnimationRunning = isAttached(); + updateExpandButtonH(); + TransitionManager.endTransitions(mDialogView); + final VolumeRow activeRow = getActiveRow(); + if (!dismissing) { + mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT); + TransitionManager.beginDelayedTransition(mDialogView, getTransition()); + } + updateRowsH(activeRow); + rescheduleTimeoutH(); + } + + private AutoTransition getTransition() { + AutoTransition transition = new AutoTransition(); + transition.setDuration(300); + transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + return transition; + } + + private void updateExpandButtonH() { + if (D.BUG) Log.d(TAG, "updateExpandButtonH"); + + mExpandButton.setClickable(!mExpandButtonAnimationRunning); + if (!(mExpandButtonAnimationRunning && isAttached())) { + final int res = mExpanded ? R.drawable.ic_volume_collapse_animation + : R.drawable.ic_volume_expand_animation; + if (hasTouchFeature()) { + mExpandButton.setImageResource(res); + } else { + // if there is no touch feature, show the volume ringer instead + mExpandButton.setImageResource(R.drawable.ic_volume_ringer); + mExpandButton.setBackgroundResource(0); // remove gray background emphasis + } + mExpandButton.setContentDescription(mContext.getString(mExpanded ? + R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand)); + } + if (mExpandButtonAnimationRunning) { + final Drawable d = mExpandButton.getDrawable(); + if (d instanceof AnimatedVectorDrawable) { + // workaround to reset drawable + final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState() + .newDrawable(); + mExpandButton.setImageDrawable(avd); + avd.start(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + mExpandButtonAnimationRunning = false; + updateExpandButtonH(); + rescheduleTimeoutH(); + } + }, 300); + } + } + } + + private boolean isAttached() { + return mDialogView != null && mDialogView.isAttachedToWindow(); + } + + private boolean hasTouchFeature() { + final PackageManager pm = mContext.getPackageManager(); + return pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN); + } + private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) { boolean isActive = row == activeRow; if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) { @@ -506,7 +588,7 @@ public class VolumeDialogImpl implements VolumeDialog { return true; } - return row.important || isActive; + return row.defaultStream || isActive || (mExpanded && row.important); } private void updateRowsH(final VolumeRow activeRow) { @@ -545,7 +627,7 @@ public class VolumeDialogImpl implements VolumeDialog { break; case AudioManager.RINGER_MODE_NORMAL: default: - boolean muted = (mAutomute && ss.level == 0) || ss.muted ? true : false; + boolean muted = (mAutomute && ss.level == 0) || ss.muted; if (muted) { mRingerStatus.setText(R.string.volume_ringer_status_silent); mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute); @@ -596,7 +678,7 @@ public class VolumeDialogImpl implements VolumeDialog { mDynamic.put(stream, true); if (findRow(stream) == null) { addRow(stream, R.drawable.ic_volume_remote, R.drawable.ic_volume_remote_mute, true, - true); + false, true); } } @@ -843,6 +925,16 @@ public class VolumeDialogImpl implements VolumeDialog { } } + private final OnClickListener mClickExpand = new OnClickListener() { + @Override + public void onClick(View v) { + mExpandButton.animate().cancel(); + final boolean newExpand = !mExpanded; + Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand); + updateExpandedH(newExpand, false /* dismissing */); + } + }; + private final VolumeDialogController.Callbacks mControllerCallbackH = new VolumeDialogController.Callbacks() { @Override @@ -898,8 +990,7 @@ public class VolumeDialogImpl implements VolumeDialog { @Override public void onAccessibilityModeChanged(Boolean showA11yStream) { - boolean show = showA11yStream == null ? false : showA11yStream; - mShowA11yStream = show; + mShowA11yStream = showA11yStream == null ? false : showA11yStream; VolumeRow activeRow = getActiveRow(); if (!mShowA11yStream && AudioManager.STREAM_ACCESSIBILITY == activeRow.stream) { dismissH(Events.DISMISS_STREAM_GONE); @@ -1100,6 +1191,7 @@ public class VolumeDialogImpl implements VolumeDialog { private int iconRes; private int iconMuteRes; private boolean important; + private boolean defaultStream; private ColorStateList cachedSliderTint; private int iconState; // from Events private ObjectAnimator anim; // slider progress animation for non-touch-related updates diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 7bc63f057f48..fcb93d252450 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -42,6 +42,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; @@ -491,7 +492,10 @@ final class AutofillManagerServiceImpl { } catch (NameNotFoundException e) { throw new SecurityException("Could not verify UID for " + componentName); } - if (callingUid != packageUid) { + // TODO(b/70506888): allow all system UIDs to call it is too broad, we should call + // something like am.isActivityRunningInProcess(componentName, callingPid), but there is + // no such API yet. + if (callingUid != packageUid && Process.isApplicationUid(callingUid)) { final String[] packages = pm.getPackagesForUid(callingUid); final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid; Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index dc35051d2dfe..37f1dc490fe3 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -889,7 +889,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Start a VR InputMethod that matches IME with package name of {@param component}. - * Note: This method is called from {@link VrManager}. + * Note: This method is called from {@link android.app.VrManager}. */ private void startVrInputMethodNoCheck(@Nullable ComponentName component) { if (component == null) { @@ -903,7 +903,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub for (InputMethodInfo info : mMethodList) { if (TextUtils.equals(info.getPackageName(), packageName) && info.isVrOnly()) { // set this is as current inputMethod without updating settings. - setInputMethodEnabled(info.getId(), true); + setInputMethodEnabledLocked(info.getId(), true); setInputMethodLocked(info.getId(), NOT_A_SUBTYPE_ID); break; } diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 219bc6114c79..36cacd7a7d96 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -1149,8 +1149,10 @@ public final class JobStore { public void forEachJob(JobStatusFunctor functor) { for (int uidIndex = mJobs.size() - 1; uidIndex >= 0; uidIndex--) { ArraySet<JobStatus> jobs = mJobs.valueAt(uidIndex); - for (int i = jobs.size() - 1; i >= 0; i--) { - functor.process(jobs.valueAt(i)); + if (jobs != null) { + for (int i = jobs.size() - 1; i >= 0; i--) { + functor.process(jobs.valueAt(i)); + } } } } diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java index 4525a4982d44..cd4bb14ee91f 100644 --- a/services/core/java/com/android/server/location/ContextHubService.java +++ b/services/core/java/com/android/server/location/ContextHubService.java @@ -742,6 +742,82 @@ public class ContextHubService extends IContextHubService.Stub { return mClientManager.registerClient(clientCallback, contextHubId); } + /** + * Loads a nanoapp binary at the specified Context hub. + * + * @param contextHubId the ID of the hub to load the binary + * @param transactionCallback the client-facing transaction callback interface + * @param nanoAppBinary the binary to load + * + * @throws RemoteException + */ + @Override + public void loadNanoAppOnHub( + int contextHubId, IContextHubTransactionCallback transactionCallback, + NanoAppBinary nanoAppBinary) throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_LOAD_NANOAPP)) { + return; + } + if (nanoAppBinary == null) { + Log.e(TAG, "NanoAppBinary cannot be null in loadNanoAppOnHub"); + transactionCallback.onTransactionComplete( + ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS); + return; + } + + ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction( + contextHubId, nanoAppBinary, transactionCallback); + addTransaction(transaction); + } + + /** + * Unloads a nanoapp from the specified Context Hub. + * + * @param contextHubId the ID of the hub to unload the nanoapp + * @param transactionCallback the client-facing transaction callback interface + * @param nanoAppId the ID of the nanoapp to unload + * + * @throws RemoteException + */ + @Override + public void unloadNanoAppFromHub( + int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId) + throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)) { + return; + } + + ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction( + contextHubId, nanoAppId, transactionCallback); + addTransaction(transaction); + } + + /** + * Queries for a list of nanoapps from the specified Context hub. + * + * @param contextHubId the ID of the hub to query + * @param transactionCallback the client-facing transaction callback interface + * + * @throws RemoteException + */ + @Override + public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback) + throws RemoteException { + checkPermissions(); + if (!checkHalProxyAndContextHubId( + contextHubId, transactionCallback, ContextHubTransaction.TYPE_QUERY_NANOAPPS)) { + return; + } + + ContextHubServiceTransaction transaction = + mTransactionManager.createQueryTransaction(contextHubId, transactionCallback); + addTransaction(transaction); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; @@ -797,6 +873,42 @@ public class ContextHubService extends IContextHubService.Stub { return 0; } + /** + * Validates the HAL proxy state and context hub ID to see if we can start the transaction. + * + * @param contextHubId the ID of the hub to start the transaction + * @param callback the client transaction callback interface + * @param transactionType the type of the transaction + * + * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise + */ + private boolean checkHalProxyAndContextHubId( + int contextHubId, IContextHubTransactionCallback callback, + @ContextHubTransaction.Type int transactionType) { + if (mContextHubProxy == null) { + try { + callback.onTransactionComplete( + ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while calling onTransactionComplete", e); + } + return false; + } + if (!isValidContextHubId(contextHubId)) { + Log.e(TAG, "Cannot start " + + ContextHubTransaction.typeToString(transactionType, false /* upperCase */) + + " transaction for invalid hub ID " + contextHubId); + try { + callback.onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while calling onTransactionComplete", e); + } + return false; + } + + return true; + } + private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) { // App Id encodes vendor & version NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo(); diff --git a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java index a543dafc1ed1..ce92f722e2d2 100644 --- a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java +++ b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java @@ -126,28 +126,9 @@ import java.util.concurrent.TimeUnit; return mIsComplete; } - /** - * @return the human-readable string of this transaction's type - */ - private String getTransactionTypeString() { - switch (mTransactionType) { - case ContextHubTransaction.TYPE_LOAD_NANOAPP: - return "Load"; - case ContextHubTransaction.TYPE_UNLOAD_NANOAPP: - return "Unload"; - case ContextHubTransaction.TYPE_ENABLE_NANOAPP: - return "Enable"; - case ContextHubTransaction.TYPE_DISABLE_NANOAPP: - return "Disable"; - case ContextHubTransaction.TYPE_QUERY_NANOAPPS: - return "Query"; - default: - return "Unknown"; - } - } - @Override public String toString() { - return getTransactionTypeString() + " transaction (ID = " + mTransactionId + ")"; + return ContextHubTransaction.typeToString(mTransactionType, true /* upperCase */) + + " transaction (ID = " + mTransactionId + ")"; } } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 2940a6e3fc8d..2041de64c8fb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -370,10 +370,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageAdded(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageAdded(packageName, userId); + } else { + mImpl.onTargetPackageAdded(packageName, userId); } } } @@ -388,10 +388,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageChanged(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageChanged(packageName, userId); + } else { + mImpl.onTargetPackageChanged(packageName, userId); } } } @@ -404,10 +404,10 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); - if (oi == null) { - mImpl.onTargetPackageUpgrading(packageName, userId); - } else { + if (oi != null) { mImpl.onOverlayPackageUpgrading(packageName, userId); + } else { + mImpl.onTargetPackageUpgrading(packageName, userId); } } } @@ -421,10 +421,10 @@ public final class OverlayManagerService extends SystemService { false); if (pi != null) { mPackageManager.cachePackageInfo(packageName, userId, pi); - if (!isOverlayPackage(pi)) { - mImpl.onTargetPackageUpgraded(packageName, userId); - } else { + if (pi.isOverlayPackage()) { mImpl.onOverlayPackageUpgraded(packageName, userId); + } else { + mImpl.onTargetPackageUpgraded(packageName, userId); } } } @@ -437,10 +437,10 @@ public final class OverlayManagerService extends SystemService { synchronized (mLock) { mPackageManager.forgetPackageInfo(packageName, userId); final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId); - if (oi == null) { - mImpl.onTargetPackageRemoved(packageName, userId); - } else { + if (oi != null) { mImpl.onOverlayPackageRemoved(packageName, userId); + } else { + mImpl.onTargetPackageRemoved(packageName, userId); } } } @@ -668,10 +668,6 @@ public final class OverlayManagerService extends SystemService { } }; - private boolean isOverlayPackage(@NonNull final PackageInfo pi) { - return pi != null && pi.overlayTarget != null; - } - private final class OverlayChangeListener implements OverlayManagerServiceImpl.OverlayChangeListener { @Override diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index db6e9749535b..253d4f5b22bb 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -102,11 +102,11 @@ final class OverlayManagerServiceImpl { mSettings.init(overlayPackage.packageName, newUserId, overlayPackage.overlayTarget, overlayPackage.applicationInfo.getBaseCodePath(), - overlayPackage.isStaticOverlay, overlayPackage.overlayPriority); + overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority); if (oi == null) { // This overlay does not exist in our settings. - if (overlayPackage.isStaticOverlay || + if (overlayPackage.isStaticOverlayPackage() || mDefaultOverlays.contains(overlayPackage.packageName)) { // Enable this overlay by default. if (DEBUG) { @@ -255,8 +255,8 @@ final class OverlayManagerServiceImpl { mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId); mSettings.init(packageName, userId, overlayPackage.overlayTarget, - overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay, - overlayPackage.overlayPriority); + overlayPackage.applicationInfo.getBaseCodePath(), + overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority); try { if (updateState(targetPackage, overlayPackage, userId)) { mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId); @@ -313,7 +313,7 @@ final class OverlayManagerServiceImpl { } // Ignore static overlays. - if (overlayPackage.isStaticOverlay) { + if (overlayPackage.isStaticOverlayPackage()) { return false; } @@ -363,7 +363,7 @@ final class OverlayManagerServiceImpl { continue; } - if (disabledOverlayPackageInfo.isStaticOverlay) { + if (disabledOverlayPackageInfo.isStaticOverlayPackage()) { // Don't touch static overlays. continue; } @@ -388,7 +388,7 @@ final class OverlayManagerServiceImpl { private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) { final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId); - if (overlayPackage == null || overlayPackage.isStaticOverlay) { + if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) { return false; } return true; @@ -483,7 +483,8 @@ final class OverlayManagerServiceImpl { throws OverlayManagerSettings.BadKeyException { // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers. if (targetPackage != null && - !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) { + !("android".equals(targetPackage.packageName) + && overlayPackage.isStaticOverlayPackage())) { mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 91ba87e84005..b946122019f9 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -40,6 +40,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS; import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP; +import static android.app.admin.DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE; import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES; import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS; import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT; @@ -296,7 +297,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DELEGATION_ENABLE_SYSTEM_APP, DELEGATION_KEEP_UNINSTALLED_PACKAGES, DELEGATION_PACKAGE_ACCESS, - DELEGATION_PERMISSION_GRANT + DELEGATION_PERMISSION_GRANT, + DELEGATION_INSTALL_EXISTING_PACKAGE, + DELEGATION_KEEP_UNINSTALLED_PACKAGES }; /** @@ -8843,6 +8846,39 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean installExistingPackage(ComponentName who, String callerPackage, + String packageName) { + synchronized (this) { + // Ensure the caller is a PO or an install existing package delegate + enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, + DELEGATION_INSTALL_EXISTING_PACKAGE); + final int callingUserId = mInjector.userHandleGetCallingUserId(); + if (!isUserAffiliatedWithDeviceLocked(callingUserId)) { + throw new SecurityException("Admin " + who + + " is neither the device owner or affiliated user's profile owner."); + } + + final long id = mInjector.binderClearCallingIdentity(); + try { + if (VERBOSE_LOG) { + Slog.v(LOG_TAG, "installing " + packageName + " for " + + callingUserId); + } + + // Install the package. + return mIPackageManager.installExistingPackageAsUser(packageName, callingUserId, + 0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY) + == PackageManager.INSTALL_SUCCEEDED; + } catch (RemoteException re) { + // shouldn't happen + return false; + } finally { + mInjector.binderRestoreCallingIdentity(id); + } + } + } + + @Override public void setAccountManagementDisabled(ComponentName who, String accountType, boolean disabled) { if (!mHasFeature) { diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java index d7b6142a5de6..942ea009f684 100644 --- a/telephony/java/android/telephony/Telephony.java +++ b/telephony/java/android/telephony/Telephony.java @@ -3342,6 +3342,12 @@ public final class Telephony { public static final String APN = "apn"; /** + * Prefix of Integrated Circuit Card Identifier. + * <P>Type: TEXT </P> + */ + public static final String ICCID_PREFIX = "iccid_prefix"; + + /** * User facing carrier name. * <P>Type: TEXT </P> */ |