Merge "Merged many autofill session metrics into AUTOFILL_REQUEST:" into pi-dev
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
index 37b7acf..8683ca1 100644
--- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
+++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
@@ -211,10 +211,10 @@
mExtras.putBoolean(key, Boolean.valueOf(value));
} else if (opt.equals("-f") || opt.equals("--foreground")) {
- mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE;
+ mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
} else if (opt.equals("-F") || opt.equals("--top")) {
- mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
+ mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
} else {
System.err.println("Error: Unknown option: " + opt);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index d278b55..4909690 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2228,6 +2228,8 @@
Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
Landroid/graphics/FontFamily;->freeze()Z
+Landroid/graphics/FontFamily;->mNativePtr:J
+Landroid/graphics/FontListParser;->parse(Ljava/io/InputStream;)Landroid/text/FontConfig;
Landroid/graphics/fonts/FontVariationAxis;->mStyleValue:F
Landroid/graphics/fonts/FontVariationAxis;->mTag:I
Landroid/graphics/GraphicBuffer;-><init>(IIIIJ)V
@@ -2374,6 +2376,7 @@
Landroid/hardware/camera2/CameraCharacteristics;->LED_AVAILABLE_LEDS:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->LENS_INFO_SHADING_MAP_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;
+Landroid/hardware/camera2/CameraCharacteristics;->mProperties:Landroid/hardware/camera2/impl/CameraMetadataNative;
Landroid/hardware/camera2/CameraCharacteristics;->QUIRKS_USE_PARTIAL_RESULT:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_CHARACTERISTICS_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
Landroid/hardware/camera2/CameraCharacteristics;->REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;
@@ -2430,6 +2433,9 @@
Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_RED:Landroid/hardware/camera2/CaptureResult$Key;
Landroid/hardware/camera2/impl/CameraMetadataNative$Key;->getTag()I
Landroid/hardware/camera2/impl/CameraMetadataNative;->mMetadataPtr:J
+Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeGetTagFromKeyLocal(Ljava/lang/String;)I
+Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeGetTypeFromTagLocal(I)I
+Landroid/hardware/camera2/impl/CameraMetadataNative;->nativeReadValues(I)[B
Landroid/hardware/camera2/utils/SurfaceUtils;->getSurfaceSize(Landroid/view/Surface;)Landroid/util/Size;
Landroid/hardware/camera2/utils/TypeReference;-><init>()V
Landroid/hardware/camera2/utils/TypeReference;->createSpecializedTypeReference(Ljava/lang/reflect/Type;)Landroid/hardware/camera2/utils/TypeReference;
@@ -3777,6 +3783,7 @@
Landroid/os/BatteryStats$Timer;-><init>()V
Landroid/os/BatteryStats$Timer;->getTotalTimeLocked(JI)J
Landroid/os/BatteryStats$Uid$Pkg$Serv;->getLaunches(I)I
+Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStarts(I)I
Landroid/os/BatteryStats$Uid$Pkg$Serv;->getStartTime(JI)J
Landroid/os/BatteryStats$Uid$Pkg;-><init>()V
Landroid/os/BatteryStats$Uid$Pkg;->getServiceStats()Landroid/util/ArrayMap;
@@ -3811,12 +3818,20 @@
Landroid/os/BatteryStats$Uid;->getWifiMulticastTime(JI)J
Landroid/os/BatteryStats$Uid;->getWifiScanTime(JI)J
Landroid/os/BatteryStats;-><init>()V
+Landroid/os/BatteryStats;->computeBatteryRealtime(JI)J
Landroid/os/BatteryStats;->computeBatteryTimeRemaining(J)J
Landroid/os/BatteryStats;->computeBatteryUptime(JI)J
Landroid/os/BatteryStats;->computeChargeTimeRemaining(J)J
+Landroid/os/BatteryStats;->getBatteryUptime(J)J
+Landroid/os/BatteryStats;->getGlobalWifiRunningTime(JI)J
Landroid/os/BatteryStats;->getMobileRadioActiveTime(JI)J
Landroid/os/BatteryStats;->getNetworkActivityBytes(II)J
+Landroid/os/BatteryStats;->getPhoneOnTime(JI)J
+Landroid/os/BatteryStats;->getPhoneSignalStrengthTime(IJI)J
+Landroid/os/BatteryStats;->getScreenBrightnessTime(IJI)J
+Landroid/os/BatteryStats;->getScreenOnTime(JI)J
Landroid/os/BatteryStats;->getUidStats()Landroid/util/SparseArray;
+Landroid/os/BatteryStats;->getWifiOnTime(JI)J
Landroid/os/BatteryStats;->NUM_DATA_CONNECTION_TYPES:I
Landroid/os/BatteryStats;->NUM_SCREEN_BRIGHTNESS_BINS:I
Landroid/os/BatteryStats;->startIteratingHistoryLocked()Z
@@ -5276,6 +5291,7 @@
Landroid/telephony/PhoneNumberUtils;->MIN_MATCH:I
Landroid/telephony/PhoneNumberUtils;->ttsSpanAsPhoneNumber(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
Landroid/telephony/PhoneStateListener;-><init>(Landroid/os/Looper;)V
+Landroid/telephony/PhoneStateListener;->callback:Lcom/android/internal/telephony/IPhoneStateListener;
Landroid/telephony/PhoneStateListener;->LISTEN_PRECISE_CALL_STATE:I
Landroid/telephony/PhoneStateListener;->mSubId:Ljava/lang/Integer;
Landroid/telephony/PhoneStateListener;->onDataConnectionRealTimeInfoChanged(Landroid/telephony/DataConnectionRealTimeInfo;)V
@@ -5537,6 +5553,14 @@
Landroid/text/DynamicLayout;->getNumberOfBlocks()I
Landroid/text/DynamicLayout;->setIndexFirstChangedBlock(I)V
Landroid/text/DynamicLayout;->sStaticLayout:Landroid/text/StaticLayout;
+Landroid/text/FontConfig$Family;->getFonts()[Landroid/text/FontConfig$Font;
+Landroid/text/FontConfig$Family;->getName()Ljava/lang/String;
+Landroid/text/FontConfig$Family;->getVariant()I
+Landroid/text/FontConfig$Font;->getAxes()[Landroid/graphics/fonts/FontVariationAxis;
+Landroid/text/FontConfig$Font;->getTtcIndex()I
+Landroid/text/FontConfig$Font;->getWeight()I
+Landroid/text/FontConfig$Font;->isItalic()Z
+Landroid/text/FontConfig;->getFamilies()[Landroid/text/FontConfig$Family;
Landroid/text/format/DateFormat;->getTimeFormatString(Landroid/content/Context;)Ljava/lang/String;
Landroid/text/format/DateFormat;->getTimeFormatString(Landroid/content/Context;I)Ljava/lang/String;
Landroid/text/format/DateFormat;->hasDesignator(Ljava/lang/CharSequence;C)Z
@@ -7400,6 +7424,7 @@
Lcom/android/internal/app/AlertController;->setMessage(Ljava/lang/CharSequence;)V
Lcom/android/internal/app/AlertController;->setTitle(Ljava/lang/CharSequence;)V
Lcom/android/internal/app/AlertController;->setView(Landroid/view/View;)V
+Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->setMode(IILjava/lang/String;I)V
@@ -8174,6 +8199,7 @@
Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ISub$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISub;
+Lcom/android/internal/telephony/ISub;->getActiveSubIdList()[I
Lcom/android/internal/telephony/ISub;->getDefaultDataSubId()I
Lcom/android/internal/telephony/ISub;->getDefaultSubId()I
Lcom/android/internal/telephony/ISub;->setDefaultDataSubId(I)V
@@ -8997,6 +9023,20 @@
Lorg/apache/http/conn/ssl/SSLSocketFactory;->sslcontext:Ljavax/net/ssl/SSLContext;
Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
+Lorg/ccil/cowan/tagsoup/ElementType;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/ElementType;->theFlags:I
+Lorg/ccil/cowan/tagsoup/ElementType;->theLocalName:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/ElementType;->theMemberOf:I
+Lorg/ccil/cowan/tagsoup/ElementType;->theModel:I
+Lorg/ccil/cowan/tagsoup/ElementType;->theName:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/ElementType;->theNamespace:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/ElementType;->theParent:Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/ElementType;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/Schema;->theElementTypes:Ljava/util/HashMap;
+Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
+Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Schema;->theRoot:Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/Schema;->theURI:Ljava/lang/String;
Lorg/json/JSONArray;->values:Ljava/util/List;
Lorg/json/JSONArray;->writeTo(Lorg/json/JSONStringer;)V
Lorg/json/JSONObject;->append(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index 2d007ad..60e8a12 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -144,13 +144,6 @@
* @param bitmap Source where to extract from.
*/
public static WallpaperColors fromBitmap(@NonNull Bitmap bitmap) {
- return fromBitmap(bitmap, false /* computeHints */);
- }
-
- /**
- * @hide
- */
- public static WallpaperColors fromBitmap(@NonNull Bitmap bitmap, boolean computeHints) {
if (bitmap == null) {
throw new IllegalArgumentException("Bitmap can't be null");
}
@@ -200,7 +193,7 @@
}
}
- int hints = computeHints ? calculateDarkHints(bitmap) : 0;
+ int hints = calculateDarkHints(bitmap);
if (shouldRecycle) {
bitmap.recycle();
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1b07784..72d209a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -184,7 +184,11 @@
/** @hide */
public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A;
/** @hide */
- public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000B;
+ public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE = 0x000B;
+ /** @hide */
+ public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
+ /** @hide */
+ public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
/** @hide */
public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001;
@@ -669,13 +673,19 @@
sb.append("-sa");
break;
case REASON_SUB_USAGE_SLICE_PINNED:
- sb.append("slp");
+ sb.append("-lp");
break;
case REASON_SUB_USAGE_SLICE_PINNED_PRIV:
- sb.append("slpp");
+ sb.append("-lv");
+ break;
+ case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE:
+ sb.append("-en");
+ break;
+ case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE:
+ sb.append("-ed");
break;
case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
- sb.append("es");
+ sb.append("-es");
break;
}
break;
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index b8628a4..1a656ab 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -245,7 +245,15 @@
int numDeferredJobs, long timeSinceLastJobRun);
/**
- * Report a sync that was scheduled by an active app is about to be executed.
+ * Report a sync is scheduled by a foreground app.
+ *
+ * @param packageName name of the package that owns the sync adapter.
+ * @param userId which user the app is associated with
+ */
+ public abstract void reportExemptedSyncScheduled(String packageName, @UserIdInt int userId);
+
+ /**
+ * Report a sync that was scheduled by a foreground app is about to be executed.
*
* @param packageName name of the package that owns the sync adapter.
* @param userId which user the app is associated with
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f7908b6..32a6743 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -520,27 +520,36 @@
public static final int SYNC_EXEMPTION_NONE = 0;
/**
- * When executing a sync with this exemption, we'll put the target app in the ACTIVE bucket
- * for 10 minutes. This will allow the sync adapter to schedule/run further syncs and jobs.
+ * Exemption given to a sync request made by a foreground app (including
+ * PROCESS_STATE_IMPORTANT_FOREGROUND).
*
- * Note this will still *not* let RARE apps to run syncs, because they still won't get network
- * connection.
+ * At the schedule time, we promote the sync adapter app for a higher bucket:
+ * - If the device is not dozing (so the sync will start right away)
+ * promote to ACTIVE for 1 hour.
+ * - If the device is dozing (so the sync *won't* start right away),
+ * promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the
+ * device comes out of doze.
+ * - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes,
+ * so it can schedule and start more syncs without getting throttled, even when the first
+ * operation was canceled and now we're retrying.
+ *
+ *
* @hide
*/
- public static final int SYNC_EXEMPTION_ACTIVE = 1;
+ public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1;
/**
- * In addition to {@link #SYNC_EXEMPTION_ACTIVE}, we put the sync adapter app in the
+ * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the
* temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
* @hide
*/
- public static final int SYNC_EXEMPTION_ACTIVE_WITH_TEMP = 2;
+ public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2;
/** @hide */
@IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = {
SYNC_EXEMPTION_NONE,
- SYNC_EXEMPTION_ACTIVE,
- SYNC_EXEMPTION_ACTIVE_WITH_TEMP,
+ SYNC_EXEMPTION_PROMOTE_BUCKET,
+ SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SyncExemption {}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c988fa9..03e600e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -598,6 +598,8 @@
boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
+ boolean setSystemAppInstallState(String packageName, boolean installed, int userId);
+
IPackageInstaller getPackageInstaller();
boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c3548e5..15aedd7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -147,6 +147,7 @@
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PackageInfoFlags {}
@@ -164,6 +165,7 @@
MATCH_STATIC_SHARED_LIBRARIES,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoFlags {}
@@ -521,6 +523,12 @@
public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x10000000;
/**
+ * Internal flag used to indicate that a package is a hidden system app.
+ * @hide
+ */
+ public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 0x20000000;
+
+ /**
* Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
* resolving an intent that matches the {@code CrossProfileIntentFilter},
* the current profile will be skipped. Only activities in the target user
@@ -4839,7 +4847,8 @@
* on the system for other users, also install it for the specified user.
* @hide
*/
- @RequiresPermission(anyOf = {
+ @RequiresPermission(anyOf = {
+ Manifest.permission.INSTALL_EXISTING_PACKAGES,
Manifest.permission.INSTALL_PACKAGES,
Manifest.permission.INTERACT_ACROSS_USERS_FULL})
public abstract int installExistingPackageAsUser(String packageName, @UserIdInt int userId)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 2da2cb4..b8eb074 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -639,11 +639,19 @@
*/
private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
ApplicationInfo appInfo) {
+ // Returns false if the package is hidden system app until installed.
+ if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
+ && !state.installed
+ && appInfo != null && appInfo.isSystemApp()) {
+ return false;
+ }
+
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return state.isAvailable(flags)
|| (appInfo != null && appInfo.isSystemApp()
- && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
+ && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
+ || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
}
public static boolean isAvailable(PackageUserState state) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4279b19..87c64cd 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -81,6 +81,15 @@
*
* @hide
*/
+ public Key(String name, String fallbackName, Class<T> type) {
+ mKey = new CameraMetadataNative.Key<T>(name, fallbackName, type);
+ }
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
public Key(String name, Class<T> type) {
mKey = new CameraMetadataNative.Key<T>(name, type);
}
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index c156616..6439338 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -87,6 +87,15 @@
*
* @hide
*/
+ public Key(String name, String fallbackName, Class<T> type) {
+ mKey = new CameraMetadataNative.Key<T>(name, fallbackName, type);
+ }
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
public Key(String name, Class<T> type) {
mKey = new CameraMetadataNative.Key<T>(name, type);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index e4b1339..4baf263 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -84,6 +84,7 @@
private final Class<T> mType;
private final TypeReference<T> mTypeReference;
private final String mName;
+ private final String mFallbackName;
private final int mHash;
/**
@@ -96,6 +97,7 @@
throw new NullPointerException("Type needs to be non-null");
}
mName = name;
+ mFallbackName = null;
mType = type;
mVendorId = vendorId;
mTypeReference = TypeReference.createSpecializedTypeReference(type);
@@ -103,6 +105,22 @@
}
/**
+ * @hide
+ */
+ public Key(String name, String fallbackName, Class<T> type) {
+ if (name == null) {
+ throw new NullPointerException("Key needs a valid name");
+ } else if (type == null) {
+ throw new NullPointerException("Type needs to be non-null");
+ }
+ mName = name;
+ mFallbackName = fallbackName;
+ mType = type;
+ mTypeReference = TypeReference.createSpecializedTypeReference(type);
+ mHash = mName.hashCode() ^ mTypeReference.hashCode();
+ }
+
+ /**
* Visible for testing only.
*
* <p>Use the CameraCharacteristics.Key, CaptureResult.Key, or CaptureRequest.Key
@@ -115,6 +133,7 @@
throw new NullPointerException("Type needs to be non-null");
}
mName = name;
+ mFallbackName = null;
mType = type;
mTypeReference = TypeReference.createSpecializedTypeReference(type);
mHash = mName.hashCode() ^ mTypeReference.hashCode();
@@ -134,6 +153,7 @@
throw new NullPointerException("TypeReference needs to be non-null");
}
mName = name;
+ mFallbackName = null;
mType = (Class<T>)typeReference.getRawType();
mTypeReference = typeReference;
mHash = mName.hashCode() ^ mTypeReference.hashCode();
@@ -494,7 +514,16 @@
int tag = nativeGetTagFromKeyLocal(key.getName());
byte[] values = readValues(tag);
if (values == null) {
- return null;
+ // If the key returns null, use the fallback key if exists.
+ // This is to support old key names for the newly published keys.
+ if (key.mFallbackName == null) {
+ return null;
+ }
+ tag = nativeGetTagFromKeyLocal(key.mFallbackName);
+ values = readValues(tag);
+ if (values == null) {
+ return null;
+ }
}
int nativeType = nativeGetTypeFromTagLocal(tag);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b13f831..2d8b4d4 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -43,6 +43,7 @@
DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
DEFAULT_FLAGS.put("settings_data_usage_v2", "true");
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
+ DEFAULT_FLAGS.put("settings_systemui_theme", "false");
}
/**
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index aee0aa7..dc1194b 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -120,7 +120,7 @@
synchronized (mLock) {
if (mSettings == null) {
mSettings = TextClassificationConstants.loadFromString(Settings.Global.getString(
- mContext.getApplicationContext().getContentResolver(),
+ getApplicationContext().getContentResolver(),
Settings.Global.TEXT_CLASSIFIER_CONSTANTS));
}
return mSettings;
@@ -186,8 +186,8 @@
protected void finalize() throws Throwable {
try {
// Note that fields could be null if the constructor threw.
- if (mContext != null && mSettingsObserver != null) {
- mContext.getApplicationContext().getContentResolver()
+ if (mSettingsObserver != null) {
+ getApplicationContext().getContentResolver()
.unregisterContentObserver(mSettingsObserver);
}
} finally {
@@ -240,6 +240,12 @@
}
}
+ Context getApplicationContext() {
+ return mContext.getApplicationContext() != null
+ ? mContext.getApplicationContext()
+ : mContext;
+ }
+
/** @hide */
public static TextClassificationConstants getSettings(Context context) {
Preconditions.checkNotNull(context);
@@ -261,7 +267,7 @@
SettingsObserver(TextClassificationManager tcm) {
super(null);
mTcm = new WeakReference<>(tcm);
- tcm.mContext.getApplicationContext().getContentResolver().registerContentObserver(
+ tcm.getApplicationContext().getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.TEXT_CLASSIFIER_CONSTANTS),
false /* notifyForDescendants */,
this);
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index b49aace..a6b29c5 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -409,10 +409,9 @@
}
mBluetoothPowerCalculator.reset();
- if (mSensorPowerCalculator == null) {
- mSensorPowerCalculator = new SensorPowerCalculator(mPowerProfile,
- (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE));
- }
+ mSensorPowerCalculator = new SensorPowerCalculator(mPowerProfile,
+ (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE),
+ mStats, rawRealtimeUs, statsType);
mSensorPowerCalculator.reset();
if (mCameraPowerCalculator == null) {
diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
index 8586d76..9e8f06d 100644
--- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
+++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
@@ -50,11 +50,33 @@
}
public MobileRadioPowerCalculator(PowerProfile profile, BatteryStats stats) {
- mPowerRadioOn = profile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE);
- for (int i = 0; i < mPowerBins.length; i++) {
- mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
+ double temp =
+ profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ACTIVE, -1);
+ if (temp != -1) {
+ mPowerRadioOn = temp;
+ } else {
+ double sum = 0;
+ sum += profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX);
+ for (int i = 0; i < mPowerBins.length; i++) {
+ sum += profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i);
+ }
+ mPowerRadioOn = sum / (mPowerBins.length + 1);
}
- mPowerScan = profile.getAveragePower(PowerProfile.POWER_RADIO_SCANNING);
+
+ temp = profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_ON, -1);
+ if (temp != -1 ) {
+ for (int i = 0; i < mPowerBins.length; i++) {
+ mPowerBins[i] = profile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
+ }
+ } else {
+ double idle = profile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE);
+ mPowerBins[0] = idle * 25 / 180;
+ for (int i = 1; i < mPowerBins.length; i++) {
+ mPowerBins[i] = Math.max(1, idle / 256);
+ }
+ }
+
+ mPowerScan = profile.getAveragePowerOrDefault(PowerProfile.POWER_RADIO_SCANNING, 0);
mStats = stats;
}
diff --git a/core/java/com/android/internal/os/SensorPowerCalculator.java b/core/java/com/android/internal/os/SensorPowerCalculator.java
index c98639b..04cb49a 100644
--- a/core/java/com/android/internal/os/SensorPowerCalculator.java
+++ b/core/java/com/android/internal/os/SensorPowerCalculator.java
@@ -20,20 +20,23 @@
import android.os.BatteryStats;
import android.util.SparseArray;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
+
import java.util.List;
public class SensorPowerCalculator extends PowerCalculator {
private final List<Sensor> mSensors;
- private final double mGpsPowerOn;
+ private final double mGpsPower;
- public SensorPowerCalculator(PowerProfile profile, SensorManager sensorManager) {
+ public SensorPowerCalculator(PowerProfile profile, SensorManager sensorManager,
+ BatteryStats stats, long rawRealtimeUs, int statsType) {
mSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
- mGpsPowerOn = profile.getAveragePower(PowerProfile.POWER_GPS_ON);
+ mGpsPower = getAverageGpsPower(profile, stats, rawRealtimeUs, statsType);
}
@Override
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
+ long rawUptimeUs, int statsType) {
// Process Sensor usage
final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
final int NSE = sensorStats.size();
@@ -42,10 +45,11 @@
final int sensorHandle = sensorStats.keyAt(ise);
final BatteryStats.Timer timer = sensor.getSensorTime();
final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
+
switch (sensorHandle) {
case BatteryStats.Uid.Sensor.GPS:
app.gpsTimeMs = sensorTime;
- app.gpsPowerMah = (app.gpsTimeMs * mGpsPowerOn) / (1000*60*60);
+ app.gpsPowerMah = (app.gpsTimeMs * mGpsPower) / (1000*60*60);
break;
default:
final int sensorsCount = mSensors.size();
@@ -60,4 +64,26 @@
}
}
}
+
+ private double getAverageGpsPower(PowerProfile profile, BatteryStats stats, long rawRealtimeUs,
+ int statsType) {
+ double averagePower =
+ profile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1);
+ if (averagePower != -1) {
+ return averagePower;
+ }
+ averagePower = 0;
+ long totalTime = 0;
+ double totalPower = 0;
+ for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType);
+ totalTime += timePerLevel;
+ totalPower += profile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
+ * timePerLevel;
+ }
+ if (totalTime != 0) {
+ averagePower = totalPower / totalTime;
+ }
+ return averagePower;
+ }
}
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 567bb07..a794b7b 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1770,20 +1770,79 @@
status_t err = OK;
// Set up rectilinear distortion correction
- camera_metadata_entry entry3 =
- results.find(ANDROID_LENS_RADIAL_DISTORTION);
+ float distortion[6] {1.f, 0.f, 0.f, 0.f, 0.f, 0.f};
+ bool gotDistortion = false;
+
camera_metadata_entry entry4 =
results.find(ANDROID_LENS_INTRINSIC_CALIBRATION);
- if (entry3.count == 6 && entry4.count == 5) {
+ if (entry4.count == 5) {
float cx = entry4.data.f[/*c_x*/2];
float cy = entry4.data.f[/*c_y*/3];
- err = builder.addWarpRectilinearForMetadata(entry3.data.f, preWidth, preHeight, cx,
- cy);
- if (err != OK) {
- ALOGE("%s: Could not add distortion correction.", __FUNCTION__);
- jniThrowRuntimeException(env, "failed to add distortion correction.");
- return nullptr;
+ // Assuming f_x = f_y, or at least close enough.
+ // Also assuming s = 0, or at least close enough.
+ float f = entry4.data.f[/*f_x*/0];
+
+ camera_metadata_entry entry3 =
+ results.find(ANDROID_LENS_DISTORTION);
+ if (entry3.count == 5) {
+ gotDistortion = true;
+ float m_x = std::fmaxf(preWidth - cx, cx);
+ float m_y = std::fmaxf(preHeight - cy, cy);
+ float m_sq = m_x*m_x + m_y*m_y;
+ float m = sqrtf(m_sq); // distance to farthest corner from optical center
+ float f_sq = f * f;
+ // Conversion factors from Camera2 K factors for new LENS_DISTORTION field
+ // to DNG spec.
+ //
+ // Camera2 / OpenCV assume distortion is applied in a space where focal length
+ // is factored out, while DNG assumes a normalized space where the distance
+ // from optical center to the farthest corner is 1.
+ // Scale from camera2 to DNG spec accordingly.
+ // distortion[0] is always 1 with the new LENS_DISTORTION field.
+ const double convCoeff[5] = {
+ m_sq / f_sq,
+ pow(m_sq, 2) / pow(f_sq, 2),
+ pow(m_sq, 3) / pow(f_sq, 3),
+ m / f,
+ m / f
+ };
+ for (size_t i = 0; i < entry3.count; i++) {
+ distortion[i+1] = convCoeff[i] * entry3.data.f[i];
+ }
+ } else {
+ entry3 = results.find(ANDROID_LENS_RADIAL_DISTORTION);
+ if (entry3.count == 6) {
+ gotDistortion = true;
+ // Conversion factors from Camera2 K factors to DNG spec. K factors:
+ //
+ // Note: these are necessary because our unit system assumes a
+ // normalized max radius of sqrt(2), whereas the DNG spec's
+ // WarpRectilinear opcode assumes a normalized max radius of 1.
+ // Thus, each K coefficient must include the domain scaling
+ // factor (the DNG domain is scaled by sqrt(2) to emulate the
+ // domain used by the Camera2 specification).
+ const double convCoeff[6] = {
+ sqrt(2),
+ 2 * sqrt(2),
+ 4 * sqrt(2),
+ 8 * sqrt(2),
+ 2,
+ 2
+ };
+ for (size_t i = 0; i < entry3.count; i++) {
+ distortion[i] = entry3.data.f[i] * convCoeff[i];
+ }
+ }
+ }
+ if (gotDistortion) {
+ err = builder.addWarpRectilinearForMetadata(distortion, preWidth, preHeight, cx,
+ cy);
+ if (err != OK) {
+ ALOGE("%s: Could not add distortion correction.", __FUNCTION__);
+ jniThrowRuntimeException(env, "failed to add distortion correction.");
+ return nullptr;
+ }
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e35b631..19e5e21 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3024,6 +3024,15 @@
<permission android:name="android.permission.INSTALL_PACKAGE_UPDATES"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to install existing system packages. This is a limited
+ version of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ <p>Not for use by third-party applications.
+ TODO(b/80204953): remove this permission once we have a long-term solution.
+ @hide
+ -->
+ <permission android:name="com.android.permission.INSTALL_EXISTING_PACKAGES"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an application to clear user data.
<p>Not for use by third-party applications
@hide
diff --git a/core/res/res/drawable/perm_group_camera.xml b/core/res/res/drawable/perm_group_camera.xml
index 61903a5..db7833f 100644
--- a/core/res/res/drawable/perm_group_camera.xml
+++ b/core/res/res/drawable/perm_group_camera.xml
@@ -22,10 +22,8 @@
<path
android:fillColor="#000000"
- android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
+ android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19z"/>
<path
android:fillColor="#000000"
- android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9
-2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5
-5-2.24 5-5 5z" />
-</vector>
\ No newline at end of file
+ android:pathData="M12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_contacts.xml b/core/res/res/drawable/perm_group_contacts.xml
index 8f9dc3e..b834a27 100644
--- a/core/res/res/drawable/perm_group_contacts.xml
+++ b/core/res/res/drawable/perm_group_contacts.xml
@@ -22,8 +22,14 @@
<path
android:fillColor="#000000"
- android:pathData="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1
-0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25
-2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5
-.83 5 2.5V17z" />
-</vector>
\ No newline at end of file
+ android:pathData="M4,1h16v2h-16z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M4,21h16v2h-16z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M20,5H4C2.9,5 2,5.9 2,7v10c0,1.1 0.9,2 2,2h2h12h2c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM8.21,17c0.7,-0.47 2.46,-1 3.79,-1s3.09,0.53 3.79,1H8.21zM20,17h-2c0,-1.99 -4,-3 -6,-3s-6,1.01 -6,3H4V7h16V17z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M12,13.5c1.66,0 3,-1.34 3,-3c0,-1.66 -1.34,-3 -3,-3s-3,1.34 -3,3C9,12.16 10.34,13.5 12,13.5zM12,9.5c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S11.45,9.5 12,9.5z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_location.xml b/core/res/res/drawable/perm_group_location.xml
index cc1ec90..a7fa524 100644
--- a/core/res/res/drawable/perm_group_location.xml
+++ b/core/res/res/drawable/perm_group_location.xml
@@ -22,6 +22,8 @@
<path
android:fillColor="#000000"
- android:pathData="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0
-9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
-</vector>
\ No newline at end of file
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_microphone.xml b/core/res/res/drawable/perm_group_microphone.xml
index d494e67..9b532c1 100644
--- a/core/res/res/drawable/perm_group_microphone.xml
+++ b/core/res/res/drawable/perm_group_microphone.xml
@@ -22,7 +22,8 @@
<path
android:fillColor="#000000"
- android:pathData="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3
-3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6
-6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" />
-</vector>
\ No newline at end of file
+ android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
+ <path
+ android:fillColor="#000000"
+ android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_sms.xml b/core/res/res/drawable/perm_group_sms.xml
index 47bca19e..ebcf3d1 100644
--- a/core/res/res/drawable/perm_group_sms.xml
+++ b/core/res/res/drawable/perm_group_sms.xml
@@ -22,6 +22,5 @@
<path
android:fillColor="#000000"
- android:pathData="M20 2H4c-1.1 0-1.99 .9 -1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9
-11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z" />
-</vector>
\ No newline at end of file
+ android:pathData="M20,2H4C2.9,2 2,2.9 2,4v18l4.75,-4h14C21.1,18 22,17.1 22,16V4C22,2.9 21.1,2 20,2zM20,16H4V4h16V16zM9,11H7V9h2V11zM17,11h-2V9h2V11zM13,11h-2V9h2V11z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
index 1ff1693..4b8965b 100644
--- a/core/res/res/drawable/perm_group_storage.xml
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -22,6 +22,5 @@
<path
android:fillColor="#000000"
- android:pathData="M10 4H4c-1.1 0-1.99 .9 -1.99 2L2 18c0 1.1 .9 2 2 2h16c1.1 0 2-.9
-2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" />
-</vector>
\ No newline at end of file
+ android:pathData="M20,6h-8l-2,-2H4C2.9,4 2.01,4.9 2.01,6L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8C22,6.9 21.1,6 20,6zM20,18H4V8h16V18z"/>
+</vector>
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 6d1bd45..ca7ab7e 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -541,7 +541,8 @@
throw new IllegalStateException("This should be called inside of onGetRoot or"
+ " onLoadChildren or onLoadItem methods");
}
- return new RemoteUserInfo(mCurConnection.pkg, mCurConnection.pid, mCurConnection.uid);
+ return new RemoteUserInfo(mCurConnection.pkg, mCurConnection.pid, mCurConnection.uid,
+ mCurConnection.callbacks.asBinder());
}
/**
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 16f6284..3490ff8 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -742,7 +742,12 @@
void JMediaCodec::setVideoScalingMode(int mode) {
if (mSurfaceTextureClient != NULL) {
+ // this works for components that queue to surface
native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
+ // also signal via param for components that queue to IGBP
+ sp<AMessage> msg = new AMessage;
+ msg->setInt32("android._video-scaling", mode);
+ (void)mCodec->setParameters(msg);
}
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index eda22d5..5dd01b0 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -384,6 +384,9 @@
process_media_player_call(
env, thiz, mp->getBufferingSettings(&settings),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getBufferingSettings:{%s}", settings.toString().string());
return bp.asJobject(env, gBufferingParamsFields);
@@ -555,6 +558,9 @@
process_media_player_call(
env, thiz, mp->getPlaybackSettings(&audioRate),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getPlaybackSettings: %f %f %d %d",
audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
@@ -623,6 +629,9 @@
process_media_player_call(
env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getSyncSettings: %d %d %f %f",
scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 918a375..6546cf0 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -495,6 +495,9 @@
process_media_player_call(
env, thiz, mp->getBufferingSettings(&settings),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getBufferingSettings:{%s}", settings.toString().string());
return bp.asJobject(env, gBufferingParamsFields);
@@ -662,6 +665,9 @@
process_media_player_call(
env, thiz, mp->getPlaybackSettings(&audioRate),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getPlaybackSettings: %f %f %d %d",
audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
@@ -730,6 +736,9 @@
process_media_player_call(
env, thiz, mp->getSyncSettings(&scp.sync, &scp.frameRate),
"java/lang/IllegalStateException", "unexpected error");
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
ALOGV("getSyncSettings: %d %d %f %f",
scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
diff --git a/packages/SettingsLib/res/drawable/ic_signal_location.xml b/packages/SettingsLib/res/drawable/ic_signal_location.xml
index 2f60580..1187093 100644
--- a/packages/SettingsLib/res/drawable/ic_signal_location.xml
+++ b/packages/SettingsLib/res/drawable/ic_signal_location.xml
@@ -19,11 +19,10 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
- <group
- android:translateX="0.02"
- android:translateY="0.82">
- <path
- android:pathData="M12,2C8.13,2 5,5.13 5,9c0,4.17 4.42,9.92 6.24,12.11 0.4,0.48 1.13,0.48 1.53,0C14.58,18.92 19,13.17 19,9c0,-3.87 -3.13,-7 -7,-7zM12,11.5a2.5,2.5 0,0 1,0 -5,2.5 2.5,0 0,1 0,5z"
- android:fillColor="#FFFFFFFF"/>
- </group>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
</vector>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 85bbd59..fbe52d1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2935,7 +2935,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 167;
+ private static final int SETTINGS_VERSION = 168;
private final int mUserId;
@@ -3792,6 +3792,19 @@
currentVersion = 167;
}
+ if (currentVersion == 167) {
+ // Version 167: by default, vibrate for wireless charging
+ final SettingsState globalSettings = getGlobalSettingsLocked();
+ final Setting currentSetting = globalSettings.getSettingLocked(
+ Global.CHARGING_VIBRATION_ENABLED);
+ if (currentSetting.isNull()) {
+ globalSettings.insertSettingLocked(
+ Global.CHARGING_VIBRATION_ENABLED, "1",
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ currentVersion = 168;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
index 6a7f18b..d5f8a2a 100644
--- a/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
+++ b/packages/SystemUI/res/drawable/ic_ime_switcher_default.xml
@@ -15,11 +15,11 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="20dp"
+ android:height="20dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M21,4H3C1.9,4 1,4.9 1,6v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2V6C23,4.9 22.1,4 21,4zM21,19H3V6h18V19zM9,8h2v2H9V8zM5,8h2v2H5V8zM8,16h8v1H8V16zM13,8h2v2h-2V8zM9,12h2v2H9V12zM5,12h2v2H5V12zM13,12h2v2h-2V12zM17,8h2v2h-2V8zM17,12h2v2h-2V12z"
+ android:pathData="M19,7h2v2h-2V7zM15,7h2v2h-2V7zM3,7h2v2H3V7zM7,7h2v2H7V7zM11,7h2v2h-2V7zM19,11h2v2h-2V11zM15,11h2v2h-2V11zM3,11h2v2H3V11zM7,11h2v2H7V11zM11,11h2v2h-2V11zM7,15h10v2H7V15z"
android:fillColor="?attr/singleToneColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
index 6fbc404..8d569b2 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
+ android:width="21dp"
+ android:height="21dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
index b02a252..93b2f9c8 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
@@ -19,10 +19,7 @@
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
-
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M17.25,10.15V14v3.85L14,15.95L10.69,14L14,12.05L17.25,10.15 M18.16,7.71c-0.14,0-0.28,0.04-0.42,0.12 l-4.63,2.72l-4.73,2.78c-0.52,0.3-0.52,1.05,0,1.36l4.73,2.78l4.63,2.72c0.13,0.08,0.28,0.12,0.42,0.12c0.44,0,0.84-0.36,0.84-0.86 V14V8.58C19,8.08,18.6,7.71,18.16,7.71L18.16,7.71z" />
- <path
- android:pathData="M 0 0 H 28 V 28 H 0 V 0 Z" />
+ android:pathData="M16.78,10.03l-3.97,3.97l3.97,3.97l-1.06,1.06l-5.03,-5.03l5.03,-5.03z"
+ android:fillColor="?attr/singleToneColor" />
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
index 5cc1791..d53c95b 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="28dp"
- android:height="28dp"
+ android:width="21dp"
+ android:height="21dp"
android:viewportWidth="28"
android:viewportHeight="28">
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 6c1ae99..2cd7883 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -17,14 +17,16 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:name="root"
- android:width="24dp"
- android:height="24dp"
+ android:width="21dp"
+ android:height="21dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
- <group android:name="icon" android:pivotX="12" android:pivotY="12">
+ <!-- Use scaleX to flip icon so arrows always point in the direction of motion -->
+ <group android:name="icon" android:pivotX="12" android:pivotY="12"
+ android:scaleX="?attr/rotateButtonScaleX">
<!-- Tint color to be set directly -->
<path android:fillColor="#FFFFFFFF"
- android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7z"/>
+ android:pathData="M19,12c0,1.72 -0.63,3.3 -1.66,4.52l-1.44,-1.44C16.58,14.23 17,13.17 17,12c0,-2.76 -2.24,-5 -5,-5c-0.06,0 -0.11,0.01 -0.17,0.01l1.08,1.08L11.5,9.5L8,6l3.5,-3.5l1.41,1.42l-1.09,1.09C11.88,5.01 11.94,5 12,5C15.87,5 19,8.13 19,12zM12.5,14.51l-1.41,1.41l1.06,1.06C12.1,16.99 12.05,17 12,17c-2.76,0 -5,-2.24 -5,-5c0,-1.17 0.42,-2.23 1.09,-3.08L6.66,7.48C5.62,8.7 5,10.28 5,12c0,3.87 3.13,7 7,7c0.06,0 0.13,-0.01 0.19,-0.01v0l-1.1,1.1l1.41,1.41L16,18L12.5,14.51z"/>
</group>
</vector>
</aapt:attr>
diff --git a/packages/SystemUI/res/drawable/stat_sys_location.xml b/packages/SystemUI/res/drawable/stat_sys_location.xml
index 33ac5cd..bdb0b0c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_location.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_location.xml
@@ -19,11 +19,13 @@
<vector
android:width="17dp"
android:height="17dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0s14.0,-15.5 14.0,-26.0C38.0,10.3 31.7,4.0 24.0,4.0zM24.0,23.0c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0c2.8,0.0 5.0,2.2 5.0,5.0S26.8,23.0 24.0,23.0z"/>
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
</vector>
</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml
new file mode 100644
index 0000000..94591e9
--- /dev/null
+++ b/packages/SystemUI/res/layout/contextual.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/menu_container"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_height="match_parent"
+ android:importantForAccessibility="no"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/menu"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:layout_weight="0"
+ android:scaleType="center"
+ systemui:keyCode="82"
+ systemui:playSound="false"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_menu"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/ime_switcher"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="center"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_ime_switch_button"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/rotate_suggestion"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="center"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_rotate_button"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/accessibility_button"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ android:scaleType="center"
+ android:visibility="invisible"
+ android:contentDescription="@string/accessibility_accessibility_button"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index d72021e..baaf699 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -18,16 +18,14 @@
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_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">
+ android:layout_height="match_parent">
<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">
@@ -36,6 +34,8 @@
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,6 +46,8 @@
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 0e17e5b5..6d5b7788 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
@@ -18,23 +18,26 @@
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_marginTop="@dimen/rounded_corner_content_padding"
- android:layout_marginBottom="@dimen/rounded_corner_content_padding"
- android:paddingTop="8dp"
- android:paddingBottom="8dp">
+ android:layout_height="match_parent">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
android:layout_width="match_parent"
- android:layout_height="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">
<com.android.systemui.statusbar.phone.ReverseLinearLayout
android:id="@+id/ends_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:clipChildren="false" />
+ android:paddingTop="@dimen/nav_content_padding"
+ android:paddingBottom="@dimen/nav_content_padding"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
<com.android.systemui.statusbar.phone.ReverseLinearLayout
android:id="@+id/center_group"
@@ -42,7 +45,10 @@
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
- android:clipChildren="false" />
+ android:paddingTop="@dimen/nav_content_padding"
+ android:paddingBottom="@dimen/nav_content_padding"
+ android:clipChildren="false"
+ android:clipToPadding="false" />
</com.android.systemui.statusbar.phone.NearestTouchFrame>
diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
index 7931dfe..8b56b68 100644
--- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
@@ -29,7 +29,6 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
- android:paddingStart="2dp"
android:orientation="horizontal" >
<FrameLayout
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 2ce9bfc..3f63f22 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -141,5 +141,7 @@
<!-- Used to style rotate suggestion button AVD animations -->
<attr name="rotateButtonStartAngle" format="float" />
<attr name="rotateButtonEndAngle" format="float" />
+ <attr name="rotateButtonScaleX" format="float" />
+
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 251589b..a68ba9b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -364,6 +364,7 @@
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
+ <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
<bool name="quick_settings_show_full_alarm">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 0024fe4..1aee7bc 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -201,7 +201,7 @@
<dimen name="status_bar_padding_start">6dp</dimen>
<!-- the padding on the end of the statusbar -->
- <dimen name="status_bar_padding_end">8dp</dimen>
+ <dimen name="status_bar_padding_end">6dp</dimen>
<!-- the radius of the overflow dot in the status bar -->
<dimen name="overflow_dot_radius">1dp</dimen>
@@ -938,7 +938,7 @@
<dimen name="rounded_corner_radius_bottom">0dp</dimen>
<dimen name="rounded_corner_content_padding">0dp</dimen>
<dimen name="nav_content_padding">0dp</dimen>
- <dimen name="nav_quick_scrub_track_edge_padding">42dp</dimen>
+ <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
<dimen name="nav_quick_scrub_track_thickness">2dp</dimen>
<!-- Navigation bar shadow params. -->
@@ -1007,4 +1007,7 @@
<dimen name="logout_button_margin_bottom">12dp</dimen>
<dimen name="logout_button_corner_radius">2dp</dimen>
+ <!-- How much into a DisplayCutout's bounds we can go, on each side -->
+ <dimen name="display_cutout_margin_consumption">0px</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b3f4534..e4f5989 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -506,21 +506,25 @@
<style name="RotateButtonCCWStart0">
<item name="rotateButtonStartAngle">0</item>
<item name="rotateButtonEndAngle">-90</item>
+ <item name="rotateButtonScaleX">1</item>
</style>
<style name="RotateButtonCCWStart90">
<item name="rotateButtonStartAngle">90</item>
<item name="rotateButtonEndAngle">0</item>
+ <item name="rotateButtonScaleX">1</item>
</style>
<style name="RotateButtonCWStart0">
<item name="rotateButtonStartAngle">0</item>
<item name="rotateButtonEndAngle">90</item>
+ <item name="rotateButtonScaleX">-1</item>
</style>
<style name="RotateButtonCWStart90">
<item name="rotateButtonStartAngle">90</item>
<item name="rotateButtonEndAngle">180</item>
+ <item name="rotateButtonScaleX">-1</item>
</style>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
index 96ec232..cd831d1 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
@@ -37,16 +37,12 @@
return convertDpToPixel(10);
}
- public static int getQuickScrubDragSlopPx() {
- return convertDpToPixel(20);
- }
-
public static int getQuickStepTouchSlopPx() {
return convertDpToPixel(24);
}
public static int getQuickScrubTouchSlopPx() {
- return convertDpToPixel(35);
+ return convertDpToPixel(24);
}
@Retention(RetentionPolicy.SOURCE)
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 2746a71..e347a14 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -196,6 +196,9 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
updateOrientation();
+ if (shouldDrawCutout() && mOverlay == null) {
+ setupDecorations();
+ }
}
protected void updateOrientation() {
@@ -207,10 +210,6 @@
updateLayoutParams();
updateViews();
}
-
- if (shouldDrawCutout() && mOverlay == null) {
- setupDecorations();
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index bcc33d2..086c87b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -48,7 +48,6 @@
import android.os.SystemProperties;
import android.os.UserManager;
import android.os.RemoteException;
-import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -163,8 +162,8 @@
if (mHasDismissedSwipeUpTip) {
int hasDimissedSwipeUpOnboardingCount =
getDismissedSwipeUpOnboardingCount();
- if (hasDimissedSwipeUpOnboardingCount > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
- Log.d(TAG, "Should not be reached");
+ if (hasDimissedSwipeUpOnboardingCount
+ > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
return;
}
final int swipeUpShowOnAppLauncherAfterDismiss =
@@ -174,7 +173,7 @@
: SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF;
mNumAppsLaunchedSinceSwipeUpTipDismiss++;
if (mNumAppsLaunchedSinceSwipeUpTipDismiss
- == swipeUpShowOnAppLauncherAfterDismiss) {
+ >= swipeUpShowOnAppLauncherAfterDismiss) {
mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
shouldLog = show(R.string.recents_swipe_up_onboarding);
}
@@ -189,7 +188,7 @@
if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
if (mHasDismissedQuickScrubTip) {
if (mOverviewOpenedCountSinceQuickScrubTipDismiss
- == QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
shouldLog = show(R.string.recents_quick_scrub_onboarding);
}
@@ -216,9 +215,9 @@
setHasSeenSwipeUpOnboarding(true);
}
if (fromHome) {
- setOpenedOverviewFromHomeCount(getOpenedOverviewFromHomeCount() + 1);
+ incrementOpenedOverviewFromHomeCount();
}
- setOpenedOverviewCount(getOpenedOverviewCount() + 1);
+ incrementOpenedOverviewCount();
if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
if (mHasDismissedQuickScrubTip) {
@@ -245,15 +244,12 @@
= new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
- Log.d(TAG, "View attached");
if (view == mLayout) {
mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
mLayoutAttachedToWindow = true;
if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
- Log.d(TAG, "recents_swipe_up_onboarding tip attached");
mHasDismissedSwipeUpTip = false;
} else {
- Log.d(TAG, "recents_quick_scrub_onboarding tip attached");
mHasDismissedQuickScrubTip = false;
}
}
@@ -261,11 +257,9 @@
@Override
public void onViewDetachedFromWindow(View view) {
- Log.d(TAG, "View detached");
if (view == mLayout) {
mLayoutAttachedToWindow = false;
if (view.getTag().equals(R.string.recents_quick_scrub_onboarding)) {
- Log.d(TAG, "recents_quick_scrub_onboarding tip detached");
mHasDismissedQuickScrubTip = true;
if (hasDismissedQuickScrubOnboardingOnce()) {
// If user dismisses the quick scrub tip twice, we consider user has seen it
@@ -353,29 +347,23 @@
return;
}
- Log.d(TAG, "Connecting to launcher");
if (!mOverviewProxyListenerRegistered) {
- Log.d(TAG, "Registering mOverviewProxyListener");
mOverviewProxyService.addCallback(mOverviewProxyListener);
mOverviewProxyListenerRegistered = true;
}
if (!mTaskListenerRegistered) {
- Log.d(TAG, "Registering mTaskListener");
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
mTaskListenerRegistered = true;
}
}
public void onDisconnectedFromLauncher() {
- Log.d(TAG, "Disconnecting to launcher");
if (mOverviewProxyListenerRegistered) {
- Log.d(TAG, "Unregistering mOverviewProxyListener");
mOverviewProxyService.removeCallback(mOverviewProxyListener);
mOverviewProxyListenerRegistered = false;
}
if (mTaskListenerRegistered) {
- Log.d(TAG, "Unregistering mTaskListener");
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskListener);
mTaskListenerRegistered = false;
}
@@ -403,8 +391,6 @@
// Only show in portrait.
int orientation = mContext.getResources().getConfiguration().orientation;
if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
- Log.d(TAG, "Show " + (stringRes == R.string.recents_swipe_up_onboarding
- ? "recents_swipe_up_onboarding" : "recents_quick_scrub_onboarding") + " tip");
mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mWindowManager.addView(mLayout, getWindowLayoutParams());
@@ -433,7 +419,6 @@
public void hide(boolean animate) {
if (mLayoutAttachedToWindow) {
- Log.d(TAG, "Hide tip, animated: " + animate);
if (animate) {
mLayout.animate()
.alpha(0f)
@@ -495,7 +480,6 @@
}
private void setHasSeenSwipeUpOnboarding(boolean hasSeenSwipeUpOnboarding) {
- Log.d(TAG, "setHasSeenSwipeUpOnboarding: " + hasSeenSwipeUpOnboarding);
Prefs.putBoolean(mContext, HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING, hasSeenSwipeUpOnboarding);
if (hasSeenSwipeUpOnboarding && hasSeenQuickScrubOnboarding()) {
onDisconnectedFromLauncher();
@@ -507,7 +491,6 @@
}
private void setHasSeenQuickScrubOnboarding(boolean hasSeenQuickScrubOnboarding) {
- Log.d(TAG, "setHasSeenQuickScrubOnboarding: " + hasSeenQuickScrubOnboarding);
Prefs.putBoolean(mContext, HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING,
hasSeenQuickScrubOnboarding);
if (hasSeenQuickScrubOnboarding && hasSeenSwipeUpOnboarding()) {
@@ -520,7 +503,6 @@
}
private void setDismissedSwipeUpOnboardingCount(int dismissedSwipeUpOnboardingCount) {
- Log.d(TAG, "setDismissedSwipeUpOnboardingCount: " + dismissedSwipeUpOnboardingCount);
Prefs.putInt(mContext, DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT,
dismissedSwipeUpOnboardingCount);
}
@@ -531,8 +513,6 @@
private void setHasDismissedQuickScrubOnboardingOnce(
boolean hasDismissedQuickScrubOnboardingOnce) {
- Log.d(TAG,
- "setHasDismissedQuickScrubOnboardingOnce: " + hasDismissedQuickScrubOnboardingOnce);
Prefs.putBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE,
hasDismissedQuickScrubOnboardingOnce);
}
@@ -541,8 +521,15 @@
return Prefs.getInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, 0);
}
+ private void incrementOpenedOverviewFromHomeCount() {
+ int openedOverviewFromHomeCount = getOpenedOverviewFromHomeCount();
+ if (openedOverviewFromHomeCount >= SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT) {
+ return;
+ }
+ setOpenedOverviewFromHomeCount(openedOverviewFromHomeCount + 1);
+ }
+
private void setOpenedOverviewFromHomeCount(int openedOverviewFromHomeCount) {
- Log.d(TAG, "setOpenedOverviewFromHomeCount: " + openedOverviewFromHomeCount);
Prefs.putInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, openedOverviewFromHomeCount);
}
@@ -550,8 +537,15 @@
return Prefs.getInt(mContext, OVERVIEW_OPENED_COUNT, 0);
}
+ private void incrementOpenedOverviewCount() {
+ int openedOverviewCount = getOpenedOverviewCount();
+ if (openedOverviewCount >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ return;
+ }
+ setOpenedOverviewCount(openedOverviewCount + 1);
+ }
+
private void setOpenedOverviewCount(int openedOverviewCount) {
- Log.d(TAG, "setOpenedOverviewCount: " + openedOverviewCount);
Prefs.putInt(mContext, OVERVIEW_OPENED_COUNT, openedOverviewCount);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 364ed80..6a38797 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -515,6 +515,13 @@
}
}
+ @Override
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ super.setDistanceToTopRoundness(distanceToTopRoundness);
+ mBackgroundNormal.setDistanceToTopRoundness(distanceToTopRoundness);
+ mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
+ }
+
/**
* Set an override tint color that is used for the background.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index d03da8f..f30fa6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -2795,6 +2795,24 @@
}
@Override
+ public boolean topAmountNeedsClipping() {
+ if (isGroupExpanded()) {
+ return true;
+ }
+ if (isGroupExpansionChanging()) {
+ return true;
+ }
+ if (getShowingLayout().shouldClipToRounding(true /* topRounded */,
+ false /* bottomRounded */)) {
+ return true;
+ }
+ if (mGuts != null && mGuts.getAlpha() != 0.0f) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
protected boolean childNeedsClipping(View child) {
if (child instanceof NotificationContentView) {
NotificationContentView contentView = (NotificationContentView) child;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index 67268c0..edfa61b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -76,7 +76,7 @@
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
*/
protected boolean mShouldTranslateContents;
- private boolean mClipRoundedToClipTopAmount;
+ private boolean mTopAmountRounded;
private float mDistanceToTopRoundness = -1;
private float mExtraWidthForClipping;
private int mMinimumHeightForClipping = 0;
@@ -85,7 +85,8 @@
@Override
public void getOutline(View view, Outline outline) {
if (!mCustomOutline && mCurrentTopRoundness == 0.0f
- && mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners) {
+ && mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners
+ && !mTopAmountRounded) {
int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
int left = Math.max(translation, 0);
int top = mClipTopAmount + mBackgroundTop;
@@ -145,9 +146,9 @@
return EMPTY_PATH;
}
float topRoundness = mAlwaysRoundBothCorners
- ? mOutlineRadius : mCurrentTopRoundness * mOutlineRadius;
+ ? mOutlineRadius : getCurrentBackgroundRadiusTop();
float bottomRoundness = mAlwaysRoundBothCorners
- ? mOutlineRadius : mCurrentBottomRoundness * mOutlineRadius;
+ ? mOutlineRadius : getCurrentBackgroundRadiusBottom();
if (topRoundness + bottomRoundness > height) {
float overShoot = topRoundness + bottomRoundness - height;
topRoundness -= overShoot * mCurrentTopRoundness
@@ -203,7 +204,7 @@
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
canvas.save();
Path intersectPath = null;
- if (mClipRoundedToClipTopAmount) {
+ if (mTopAmountRounded && topAmountNeedsClipping()) {
int left = (int) (- mExtraWidthForClipping / 2.0f);
int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
int right = getWidth() + (int) (mExtraWidthForClipping + left);
@@ -248,9 +249,9 @@
public void setDistanceToTopRoundness(float distanceToTopRoundness) {
super.setDistanceToTopRoundness(distanceToTopRoundness);
if (distanceToTopRoundness != mDistanceToTopRoundness) {
- mClipRoundedToClipTopAmount = distanceToTopRoundness >= 0;
+ mTopAmountRounded = distanceToTopRoundness >= 0;
mDistanceToTopRoundness = distanceToTopRoundness;
- invalidate();
+ applyRoundness();
}
}
@@ -258,9 +259,12 @@
return false;
}
+ public boolean topAmountNeedsClipping() {
+ return true;
+ }
+
protected boolean isClippingNeeded() {
return mAlwaysRoundBothCorners || mCustomOutline || getTranslation() != 0 ;
-
}
private void initDimens() {
@@ -296,6 +300,11 @@
}
public float getCurrentBackgroundRadiusTop() {
+ // If this view is top amount notification view, it should always has round corners on top.
+ // It will be applied with applyRoundness()
+ if (mTopAmountRounded) {
+ return mOutlineRadius;
+ }
return mCurrentTopRoundness * mOutlineRadius;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 0ff4dde..969e9d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -53,6 +53,9 @@
private int mDrawableAlpha = 255;
private boolean mIsPressedAllowed;
+ private boolean mTopAmountRounded;
+ private float mDistanceToTopRoundness;
+
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
mDontModifyCorners = getResources().getBoolean(
@@ -74,6 +77,7 @@
private void draw(Canvas canvas, Drawable drawable) {
if (drawable != null) {
+ int top = mBackgroundTop;
int bottom = mActualHeight;
if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) {
bottom -= mClipBottomAmount;
@@ -84,7 +88,14 @@
left = (int) ((getWidth() - mActualWidth) / 2.0f);
right = (int) (left + mActualWidth);
}
- drawable.setBounds(left, mBackgroundTop, right, bottom);
+ if (mTopAmountRounded) {
+ int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
+ top += clipTop;
+ if (clipTop >= 0) {
+ bottom += clipTop;
+ }
+ }
+ drawable.setBounds(left, top, right, bottom);
drawable.draw(canvas);
}
}
@@ -165,6 +176,14 @@
invalidate();
}
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ if (distanceToTopRoundness != mDistanceToTopRoundness) {
+ mTopAmountRounded = distanceToTopRoundness >= 0;
+ mDistanceToTopRoundness = distanceToTopRoundness;
+ invalidate();
+ }
+ }
+
@Override
public boolean hasOverlappingRendering() {
@@ -198,6 +217,9 @@
}
public void setRoundness(float topRoundness, float bottomRoundNess) {
+ if (topRoundness == mCornerRadii[0] && bottomRoundNess == mCornerRadii[4]) {
+ return;
+ }
mBottomIsRounded = bottomRoundNess != 0.0f;
mCornerRadii[0] = topRoundness;
mCornerRadii[1] = topRoundness;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 58d3b9a..0bd3cc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -90,6 +90,11 @@
private ViewGroup mStatusIconArea;
private int mLayoutState = LAYOUT_NONE;
+ /**
+ * Draw this many pixels into the left/right side of the cutout to optimally use the space
+ */
+ private int mCutoutSideNudge = 0;
+
public KeyguardStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -158,6 +163,8 @@
R.dimen.system_icons_switcher_hidden_expanded_margin);
mSystemIconsBaseMargin = res.getDimensionPixelSize(
R.dimen.system_icons_super_container_avatarless_margin_end);
+ mCutoutSideNudge = getResources().getDimensionPixelSize(
+ R.dimen.display_cutout_margin_consumption);
}
private void updateVisibilities() {
@@ -266,6 +273,8 @@
mCutoutSpace.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams lp = (LayoutParams) mCutoutSpace.getLayoutParams();
+ bounds.left = bounds.left + mCutoutSideNudge;
+ bounds.right = bounds.right - mCutoutSideNudge;
lp.width = bounds.width();
lp.height = bounds.height();
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 68359bf..9acac22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -1144,6 +1144,8 @@
mRoot.postOnAnimationDelayed(mRipple, RIPPLE_OFFSET_MS);
mRoot.postOnAnimationDelayed(mRipple, RIPPLE_INTERVAL_MS);
mRoot.postOnAnimationDelayed(mRipple, 2*RIPPLE_INTERVAL_MS);
+ mRoot.postOnAnimationDelayed(mRipple, 3*RIPPLE_INTERVAL_MS);
+ mRoot.postOnAnimationDelayed(mRipple, 4*RIPPLE_INTERVAL_MS);
}
public void stop() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 4885c2f..e6f2c33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -34,11 +34,12 @@
import android.widget.Space;
import com.android.systemui.Dependency;
+import com.android.systemui.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
-import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseFrameLayout;
+import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -67,6 +68,7 @@
public static final String KEY = "key";
public static final String LEFT = "left";
public static final String RIGHT = "right";
+ public static final String CONTEXTUAL = "contextual";
public static final String GRAVITY_SEPARATOR = ";";
public static final String BUTTON_SEPARATOR = ",";
@@ -97,6 +99,9 @@
private View mLastLandscape;
private boolean mAlternativeOrder;
+ private boolean mUsingCustomLayout;
+
+ private OverviewProxyService mOverviewProxyService;
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -105,6 +110,7 @@
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Mode displayMode = mDisplay.getMode();
isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight();
+ mOverviewProxyService = Dependency.get(OverviewProxyService.class);
}
private void createInflaters() {
@@ -136,7 +142,10 @@
}
protected String getDefaultLayout() {
- return mContext.getString(R.string.config_navBarLayout);
+ final int defaultResource = mOverviewProxyService.shouldShowSwipeUpUI()
+ ? R.string.config_navBarLayoutQuickstep
+ : R.string.config_navBarLayout;
+ return mContext.getString(defaultResource);
}
@Override
@@ -159,6 +168,7 @@
public void onTuningChanged(String key, String newValue) {
if (NAV_BAR_VIEWS.equals(key)) {
if (!Objects.equals(mCurrentLayout, newValue)) {
+ mUsingCustomLayout = newValue != null;
clearViews();
inflateLayout(newValue);
}
@@ -168,6 +178,18 @@
}
}
+ public void onLikelyDefaultLayoutChange() {
+ // Don't override custom layouts
+ if (mUsingCustomLayout) return;
+
+ // Reevaluate new layout
+ final String newValue = getDefaultLayout();
+ if (!Objects.equals(mCurrentLayout, newValue)) {
+ clearViews();
+ inflateLayout(newValue);
+ }
+ }
+
public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) {
mButtonDispatchers = buttonDispatchers;
for (int i = 0; i < buttonDispatchers.size(); i++) {
@@ -178,10 +200,12 @@
public void updateButtonDispatchersCurrentView() {
if (mButtonDispatchers != null) {
final int rotation = mDisplay.getRotation();
- final View view = rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180
- ? mRot0 : mRot90;
+ final boolean portrait = rotation == Surface.ROTATION_0
+ || rotation == Surface.ROTATION_180;
+ final View view = portrait ? mRot0 : mRot90;
for (int i = 0; i < mButtonDispatchers.size(); i++) {
- mButtonDispatchers.valueAt(i).setCurrentView(view);
+ final ButtonDispatcher dispatcher = mButtonDispatchers.valueAt(i);
+ dispatcher.setCurrentView(view);
}
}
}
@@ -288,8 +312,8 @@
addToDispatchers(v);
View lastView = landscape ? mLastLandscape : mLastPortrait;
View accessibilityView = v;
- if (v instanceof ReverseFrameLayout) {
- accessibilityView = ((ReverseFrameLayout) v).getChildAt(0);
+ if (v instanceof ReverseRelativeLayout) {
+ accessibilityView = ((ReverseRelativeLayout) v).getChildAt(0);
}
if (lastView != null) {
accessibilityView.setAccessibilityTraversalAfter(lastView.getId());
@@ -307,21 +331,33 @@
if (sizeStr == null) return v;
if (sizeStr.contains(WEIGHT_SUFFIX)) {
+ // To support gravity, wrap in RelativeLayout and apply gravity to it.
+ // Children wanting to use gravity must be smaller then the frame.
float weight = Float.parseFloat(sizeStr.substring(0, sizeStr.indexOf(WEIGHT_SUFFIX)));
- FrameLayout frame = new ReverseFrameLayout(mContext);
+ ReverseRelativeLayout frame = new ReverseRelativeLayout(mContext);
LayoutParams childParams = new LayoutParams(v.getLayoutParams());
- if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) {
- childParams.gravity = Gravity.CENTER;
- } else {
- childParams.gravity = landscape ? (start ? Gravity.BOTTOM : Gravity.TOP)
- : (start ? Gravity.START : Gravity.END);
- }
+
+ // Compute gravity to apply
+ int gravity = (landscape) ? (start ? Gravity.TOP : Gravity.BOTTOM)
+ : (start ? Gravity.START : Gravity.END);
+ if (sizeStr.endsWith(WEIGHT_CENTERED_SUFFIX)) gravity = Gravity.CENTER;
+
+ // Set default gravity, flipped if needed in reversed layouts (270 RTL and 90 LTR)
+ frame.setDefaultGravity(gravity);
+ frame.setGravity(gravity); // Apply gravity to root
+
frame.addView(v, childParams);
+
+ // Use weighting to set the width of the frame
frame.setLayoutParams(new LinearLayout.LayoutParams(0, MATCH_PARENT, weight));
+
+ // Ensure ripples can be drawn outside bounds
frame.setClipChildren(false);
frame.setClipToPadding(false);
+
return frame;
}
+
float size = Float.parseFloat(sizeStr);
ViewGroup.LayoutParams params = v.getLayoutParams();
params.width = (int) (params.width * size);
@@ -355,6 +391,8 @@
v = inflater.inflate(R.layout.nav_key_space, parent, false);
} else if (CLIPBOARD.equals(button)) {
v = inflater.inflate(R.layout.clipboard, parent, false);
+ } else if (CONTEXTUAL.equals(button)) {
+ v = inflater.inflate(R.layout.contextual, parent, false);
} else if (button.startsWith(KEY)) {
String uri = extractImage(button);
int code = extractKeycode(button);
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 a907bdd..6c66cab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -117,6 +117,7 @@
private Rect mRecentsButtonBounds = new Rect();
private Rect mRotationButtonBounds = new Rect();
private int[] mTmpPosition = new int[2];
+ private Rect mTmpRect = new Rect();
private KeyButtonDrawable mBackIcon;
private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
@@ -604,6 +605,7 @@
}
updateNavButtonIcons();
+ updateSlippery();
}
public void updateNavButtonIcons() {
@@ -745,6 +747,12 @@
public void updateStates() {
final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
+
+ if (mNavigationInflaterView != null) {
+ // Reinflate the navbar if needed, no-op unless the swipe up state changes
+ mNavigationInflaterView.onLikelyDefaultLayoutChange();
+ }
+
updateSlippery();
reloadNavIcons();
updateNavButtonIcons();
@@ -869,14 +877,27 @@
public boolean isRotateButtonVisible() { return mShowRotateButton; }
- public void setMenuContainerVisibility(boolean visible) {
- getMenuContainer().setAlpha(visible ? 1 : 0, true /* animate */);
+ /**
+ * @return the button at the given {@param x} and {@param y}.
+ */
+ ButtonDispatcher getButtonAtPosition(int x, int y) {
+ for (int i = 0; i < mButtonDispatchers.size(); i++) {
+ ButtonDispatcher button = mButtonDispatchers.valueAt(i);
+ View buttonView = button.getCurrentView();
+ if (buttonView != null) {
+ buttonView.getHitRect(mTmpRect);
+ offsetDescendantRectToMyCoords(buttonView, mTmpRect);
+ if (mTmpRect.contains(x, y)) {
+ return button;
+ }
+ }
+ }
+ return null;
}
@Override
public void onFinishInflate() {
- mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
- R.id.navigation_inflater);
+ mNavigationInflaterView = findViewById(R.id.navigation_inflater);
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -1169,10 +1190,11 @@
+ " " + visibilityToString(getWindowVisibility())
+ (offscreen ? " OFFSCREEN!" : ""));
- pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
+ pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f",
getResourceName(getCurrentView().getId()),
getCurrentView().getWidth(), getCurrentView().getHeight(),
- visibilityToString(getCurrentView().getVisibility())));
+ visibilityToString(getCurrentView().getVisibility()),
+ getCurrentView().getAlpha()));
pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
mDisabledFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 01582d0..5477f88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -74,6 +74,10 @@
private View mCutoutSpace;
@Nullable
private DisplayCutout mDisplayCutout;
+ /**
+ * Draw this many pixels into the left/right side of the cutout to optimally use the space
+ */
+ private int mCutoutSideNudge = 0;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -98,6 +102,8 @@
mBarTransitions.init();
mBattery = findViewById(R.id.battery);
mCutoutSpace = findViewById(R.id.cutout_space_view);
+
+ updateResources();
}
@Override
@@ -280,6 +286,9 @@
}
public void updateResources() {
+ mCutoutSideNudge = getResources().getDimensionPixelSize(
+ R.dimen.display_cutout_margin_consumption);
+
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = getResources().getDimensionPixelSize(
R.dimen.status_bar_height);
@@ -311,6 +320,8 @@
Rect bounds = new Rect();
boundsFromDirection(mDisplayCutout, Gravity.TOP, bounds);
+ bounds.left = bounds.left + mCutoutSideNudge;
+ bounds.right = bounds.right - mCutoutSideNudge;
lp.width = bounds.width();
lp.height = bounds.height();
}
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 d9ba313..b55fe47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -16,20 +16,30 @@
package com.android.systemui.statusbar.phone;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static com.android.systemui.Interpolators.ALPHA_IN;
+import static com.android.systemui.Interpolators.ALPHA_OUT;
+import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.OverviewProxyService.TAG_OPS;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
+import android.util.FloatProperty;
import android.util.Log;
import android.util.Slog;
import android.view.MotionEvent;
@@ -46,30 +56,22 @@
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.NavigationBarCompat;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
-
/**
* Class to detect gestures on the navigation bar and implement quick scrub.
*/
public class QuickStepController implements GestureHelper {
private static final String TAG = "QuickStepController";
- private static final int ANIM_DURATION_MS = 200;
+ private static final int ANIM_IN_DURATION_MS = 150;
+ private static final int ANIM_OUT_DURATION_MS = 100;
private NavigationBarView mNavigationBarView;
private boolean mQuickScrubActive;
private boolean mAllowGestureDetection;
private boolean mQuickStepStarted;
- private float mDownOffset;
- private float mTranslation;
private int mTouchDownX;
private int mTouchDownY;
- private boolean mDragScrubActive;
private boolean mDragPositive;
private boolean mIsVertical;
private boolean mIsRTL;
@@ -77,69 +79,67 @@
private int mLightTrackColor;
private int mDarkTrackColor;
private float mDarkIntensity;
- private View mHomeButtonView;
+ private AnimatorSet mTrackAnimator;
+ private ButtonDispatcher mHitTarget;
+ private View mCurrentNavigationBarView;
private final Handler mHandler = new Handler();
- private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
private final Rect mTrackRect = new Rect();
private final Paint mTrackPaint = new Paint();
private final OverviewProxyService mOverviewEventSender;
private final int mTrackThickness;
- private final int mTrackPadding;
- private final ValueAnimator mTrackAnimator;
- private final ValueAnimator mButtonAnimator;
- private final AnimatorSet mQuickScrubEndAnimator;
+ private final int mTrackEndPadding;
private final Context mContext;
private final Matrix mTransformGlobalMatrix = new Matrix();
private final Matrix mTransformLocalMatrix = new Matrix();
private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
- private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
- mTrackAlpha = (float) valueAnimator.getAnimatedValue();
- mNavigationBarView.invalidate();
+ private final FloatProperty<QuickStepController> mTrackAlphaProperty =
+ new FloatProperty<QuickStepController>("TrackAlpha") {
+ @Override
+ public void setValue(QuickStepController controller, float alpha) {
+ mTrackAlpha = alpha;
+ mNavigationBarView.invalidate();
+ }
+
+ @Override
+ public Float get(QuickStepController controller) {
+ return mTrackAlpha;
+ }
};
- private final AnimatorUpdateListener mButtonTranslationListener = animator -> {
- int pos = (int) animator.getAnimatedValue();
- if (!mQuickScrubActive) {
- pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
+ private final FloatProperty<QuickStepController> mNavBarAlphaProperty =
+ new FloatProperty<QuickStepController>("NavBarAlpha") {
+ @Override
+ public void setValue(QuickStepController controller, float alpha) {
+ if (mCurrentNavigationBarView != null) {
+ mCurrentNavigationBarView.setAlpha(alpha);
+ }
}
- if (mIsVertical) {
- mHomeButtonView.setTranslationY(pos);
- } else {
- mHomeButtonView.setTranslationX(pos);
+
+ @Override
+ public Float get(QuickStepController controller) {
+ if (mCurrentNavigationBarView != null) {
+ return mCurrentNavigationBarView.getAlpha();
+ }
+ return 1f;
}
};
private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mQuickScrubActive = false;
- mDragScrubActive = false;
- mTranslation = 0;
- mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
- mHomeButtonView = null;
+ resetQuickScrub();
}
};
public QuickStepController(Context context) {
+ final Resources res = context.getResources();
mContext = context;
mOverviewEventSender = Dependency.get(OverviewProxyService.class);
- mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
- mTrackPadding = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_edge_padding);
+ mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
+ mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
mTrackPaint.setAlpha(0);
-
- mTrackAnimator = ObjectAnimator.ofFloat();
- mTrackAnimator.addUpdateListener(mTrackAnimatorListener);
- mTrackAnimator.setFloatValues(0);
- mButtonAnimator = ObjectAnimator.ofInt();
- mButtonAnimator.addUpdateListener(mButtonTranslationListener);
- mButtonAnimator.setIntValues(0);
- mQuickScrubEndAnimator = new AnimatorSet();
- mQuickScrubEndAnimator.playTogether(mTrackAnimator, mButtonAnimator);
- mQuickScrubEndAnimator.setDuration(ANIM_DURATION_MS);
- mQuickScrubEndAnimator.addListener(mQuickScrubEndListener);
- mQuickScrubEndAnimator.setInterpolator(mQuickScrubEndInterpolator);
}
public void setComponents(NavigationBarView navigationBarView) {
@@ -170,24 +170,28 @@
private boolean handleTouchEvent(MotionEvent event) {
if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
&& !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
- mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
return false;
}
mNavigationBarView.requestUnbufferedDispatch(event);
- final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
- final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
+
// End any existing quickscrub animations before starting the new transition
- if (mHomeButtonView != null) {
- mQuickScrubEndAnimator.end();
+ if (mTrackAnimator != null) {
+ mTrackAnimator.end();
+ mTrackAnimator = null;
}
- mHomeButtonView = homeButton.getCurrentView();
- homeButton.setDelayTouchFeedback(true /* delay */);
+
+ mCurrentNavigationBarView = mNavigationBarView.getCurrentView();
+ mHitTarget = mNavigationBarView.getButtonAtPosition(x, y);
+ if (mHitTarget != null) {
+ // Pre-emptively delay the touch feedback for the button that we just touched
+ mHitTarget.setDelayTouchFeedback(true);
+ }
mTouchDownX = x;
mTouchDownY = y;
mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
@@ -199,7 +203,7 @@
break;
}
case MotionEvent.ACTION_MOVE: {
- if (mQuickStepStarted || !mAllowGestureDetection || mHomeButtonView == null){
+ if (mQuickStepStarted || !mAllowGestureDetection){
break;
}
int x = (int) event.getX();
@@ -207,7 +211,7 @@
int xDiff = Math.abs(x - mTouchDownX);
int yDiff = Math.abs(y - mTouchDownY);
- boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop, exceededScrubDragSlop;
+ boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop;
int pos, touchDown, offset, trackSize;
if (mIsVertical) {
@@ -215,8 +219,6 @@
yDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && yDiff > xDiff;
exceededSwipeUpTouchSlop =
xDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && xDiff > yDiff;
- exceededScrubDragSlop =
- yDiff > NavigationBarCompat.getQuickScrubDragSlopPx() && yDiff > xDiff;
pos = y;
touchDown = mTouchDownY;
offset = pos - mTrackRect.top;
@@ -226,8 +228,6 @@
xDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && xDiff > yDiff;
exceededSwipeUpTouchSlop =
yDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && yDiff > xDiff;
- exceededScrubDragSlop =
- xDiff > NavigationBarCompat.getQuickScrubDragSlopPx() && xDiff > yDiff;
pos = x;
touchDown = mTouchDownX;
offset = pos - mTrackRect.left;
@@ -242,8 +242,8 @@
break;
}
- // Do not handle quick scrub if disabled or hit target is not home button
- if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) {
+ // Do not handle quick scrub if disabled
+ if (!mNavigationBarView.isQuickScrubEnabled()) {
break;
}
@@ -253,41 +253,23 @@
final boolean allowDrag = !mDragPositive
? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
+ float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
if (allowDrag) {
- // Passing the drag slop is for visual feedback and will not initiate anything
- if (!mDragScrubActive && exceededScrubDragSlop) {
- mDownOffset = offset;
- mDragScrubActive = true;
- }
-
// Passing the drag slop then touch slop will start quick step
if (!mQuickScrubActive && exceededScrubTouchSlop) {
- homeButton.abortCurrentGesture();
startQuickScrub();
}
}
- if ((mQuickScrubActive || mDragScrubActive) && (mDragPositive && offset >= 0
+ if (mQuickScrubActive && (mDragPositive && offset >= 0
|| !mDragPositive && offset <= 0)) {
- mTranslation = !mDragPositive
- ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
- : Utilities.clamp(offset - mDownOffset, 0, trackSize);
- if (mQuickScrubActive) {
- float scrubFraction =
- Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
- try {
- mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send progress of quick scrub.", e);
+ try {
+ mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
}
- }
- if (mIsVertical) {
- mHomeButtonView.setTranslationY(mTranslation);
- } else {
- mHomeButtonView.setTranslationX(mTranslation);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
}
break;
@@ -321,21 +303,23 @@
@Override
public void onLayout(boolean changed, int left, int top, int right, int bottom) {
- final int width = (right - left) - mNavigationBarView.getPaddingEnd()
- - mNavigationBarView.getPaddingStart();
- final int height = (bottom - top) - mNavigationBarView.getPaddingBottom()
- - mNavigationBarView.getPaddingTop();
+ final int paddingLeft = mNavigationBarView.getPaddingLeft();
+ final int paddingTop = mNavigationBarView.getPaddingTop();
+ final int paddingRight = mNavigationBarView.getPaddingRight();
+ final int paddingBottom = mNavigationBarView.getPaddingBottom();
+ final int width = (right - left) - paddingRight - paddingLeft;
+ final int height = (bottom - top) - paddingBottom - paddingTop;
final int x1, x2, y1, y2;
if (mIsVertical) {
- x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingLeft();
+ x1 = (width - mTrackThickness) / 2 + paddingLeft;
x2 = x1 + mTrackThickness;
- y1 = mDragPositive ? height / 2 : mTrackPadding;
- y2 = y1 + height / 2 - mTrackPadding;
+ y1 = paddingTop + mTrackEndPadding;
+ y2 = y1 + height - 2 * mTrackEndPadding;
} else {
- y1 = (height - mTrackThickness) / 2 + mNavigationBarView.getPaddingTop();
+ y1 = (height - mTrackThickness) / 2 + paddingTop;
y2 = y1 + mTrackThickness;
- x1 = mDragPositive ? width / 2 : mTrackPadding;
- x2 = x1 + width / 2 - mTrackPadding;
+ x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
+ x2 = x1 + width - 2 * mTrackEndPadding;
}
mTrackRect.set(x1, y1, x2, y2);
}
@@ -386,24 +370,32 @@
event.transform(mTransformLocalMatrix);
}
mOverviewEventSender.notifyQuickStepStarted();
- mNavigationBarView.getHomeButton().abortCurrentGesture();
mHandler.removeCallbacksAndMessages(null);
- if (mDragScrubActive) {
+ if (mHitTarget != null) {
+ mHitTarget.abortCurrentGesture();
+ }
+
+ if (mQuickScrubActive) {
animateEnd();
}
}
private void startQuickScrub() {
- if (!mQuickScrubActive && mDragScrubActive) {
+ if (!mQuickScrubActive) {
mQuickScrubActive = true;
mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
- mTrackAnimator.setFloatValues(0, 1);
- mTrackAnimator.start();
- // Hide menu buttons on nav bar until quick scrub has ended
- mNavigationBarView.setMenuContainerVisibility(false /* visible */);
+ ObjectAnimator trackAnimator = ObjectAnimator.ofFloat(this, mTrackAlphaProperty, 1f);
+ trackAnimator.setInterpolator(ALPHA_IN);
+ trackAnimator.setDuration(ANIM_IN_DURATION_MS);
+ ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 0f);
+ navBarAnimator.setInterpolator(ALPHA_OUT);
+ navBarAnimator.setDuration(ANIM_OUT_DURATION_MS);
+ mTrackAnimator = new AnimatorSet();
+ mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
+ mTrackAnimator.start();
try {
mOverviewEventSender.getProxy().onQuickScrubStart();
@@ -414,32 +406,56 @@
Log.e(TAG, "Failed to send start of quick scrub.", e);
}
mOverviewEventSender.notifyQuickScrubStarted();
+
+ if (mHitTarget != null) {
+ mHitTarget.abortCurrentGesture();
+ }
}
}
private void endQuickScrub(boolean animate) {
- if (mQuickScrubActive || mDragScrubActive) {
+ if (mQuickScrubActive) {
animateEnd();
-
- // Restore the nav bar menu buttons visibility
- mNavigationBarView.setMenuContainerVisibility(true /* visible */);
-
- if (mQuickScrubActive) {
- try {
- mOverviewEventSender.getProxy().onQuickScrubEnd();
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub End");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send end of quick scrub.", e);
+ try {
+ mOverviewEventSender.getProxy().onQuickScrubEnd();
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub End");
}
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send end of quick scrub.", e);
}
}
- if (mHomeButtonView != null && !animate) {
- mQuickScrubEndAnimator.end();
+ if (!animate) {
+ if (mTrackAnimator != null) {
+ mTrackAnimator.end();
+ mTrackAnimator = null;
+ }
}
}
+ private void animateEnd() {
+ if (mTrackAnimator != null) {
+ mTrackAnimator.cancel();
+ }
+
+ ObjectAnimator trackAnimator = ObjectAnimator.ofFloat(this, mTrackAlphaProperty, 0f);
+ trackAnimator.setInterpolator(ALPHA_OUT);
+ trackAnimator.setDuration(ANIM_OUT_DURATION_MS);
+ ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 1f);
+ navBarAnimator.setInterpolator(ALPHA_IN);
+ navBarAnimator.setDuration(ANIM_IN_DURATION_MS);
+ mTrackAnimator = new AnimatorSet();
+ mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
+ mTrackAnimator.addListener(mQuickScrubEndListener);
+ mTrackAnimator.start();
+ }
+
+ private void resetQuickScrub() {
+ mQuickScrubActive = false;
+ mAllowGestureDetection = false;
+ mCurrentNavigationBarView = null;
+ }
+
private boolean proxyMotionEvents(MotionEvent event) {
final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
event.transform(mTransformGlobalMatrix);
@@ -459,15 +475,4 @@
}
return false;
}
-
- private void animateEnd() {
- mButtonAnimator.setIntValues((int) mTranslation, 0);
- mTrackAnimator.setFloatValues(mTrackAlpha, 0);
- mQuickScrubEndAnimator.setCurrentPlayTime(0);
- mQuickScrubEndAnimator.start();
- }
-
- private int getDimensionPixelSize(Context context, @DimenRes int resId) {
- return context.getResources().getDimensionPixelSize(resId);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
index bcbc345..d3ec187 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
@@ -17,10 +17,11 @@
import android.annotation.Nullable;
import android.content.Context;
import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import java.util.ArrayList;
@@ -48,7 +49,7 @@
@Override
public void addView(View child) {
- reverseParams(child.getLayoutParams(), child);
+ reverseParams(child.getLayoutParams(), child, mIsLayoutReverse);
if (mIsLayoutReverse) {
super.addView(child, 0);
} else {
@@ -58,7 +59,7 @@
@Override
public void addView(View child, ViewGroup.LayoutParams params) {
- reverseParams(params, child);
+ reverseParams(params, child, mIsLayoutReverse);
if (mIsLayoutReverse) {
super.addView(child, 0, params);
} else {
@@ -94,15 +95,17 @@
}
removeAllViews();
for (int i = childCount - 1; i >= 0; i--) {
- super.addView(childList.get(i));
+ final View child = childList.get(i);
+ super.addView(child);
}
mIsLayoutReverse = isLayoutReverse;
}
}
- private static void reverseParams(ViewGroup.LayoutParams params, View child) {
+ private static void reverseParams(ViewGroup.LayoutParams params, View child,
+ boolean isLayoutReverse) {
if (child instanceof Reversable) {
- ((Reversable) child).reverse();
+ ((Reversable) child).reverse(isLayoutReverse);
}
if (child.getPaddingLeft() == child.getPaddingRight()
&& child.getPaddingTop() == child.getPaddingBottom()) {
@@ -118,20 +121,48 @@
}
public interface Reversable {
- void reverse();
+ void reverse(boolean isLayoutReverse);
}
- public static class ReverseFrameLayout extends FrameLayout implements Reversable {
+ public static class ReverseRelativeLayout extends RelativeLayout implements Reversable {
- public ReverseFrameLayout(Context context) {
+ public ReverseRelativeLayout(Context context) {
super(context);
}
@Override
- public void reverse() {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- reverseParams(child.getLayoutParams(), child);
+ public void reverse(boolean isLayoutReverse) {
+ updateGravity(isLayoutReverse);
+ reverseGroup(this, isLayoutReverse);
+ }
+
+ private int mDefaultGravity = Gravity.NO_GRAVITY;
+ public void setDefaultGravity(int gravity) {
+ mDefaultGravity = gravity;
+ }
+
+ public void updateGravity(boolean isLayoutReverse) {
+ // Flip gravity if top of bottom is used
+ if (mDefaultGravity != Gravity.TOP && mDefaultGravity != Gravity.BOTTOM) return;
+
+ // Use the default (intended for 270 LTR and 90 RTL) unless layout is otherwise
+ int gravityToApply = mDefaultGravity;
+ if (isLayoutReverse) {
+ gravityToApply = mDefaultGravity == Gravity.TOP ? Gravity.BOTTOM : Gravity.TOP;
+ }
+
+ if (getGravity() != gravityToApply) setGravity(gravityToApply);
+ }
+ }
+
+ private static void reverseGroup(ViewGroup group, boolean isLayoutReverse) {
+ for (int i = 0; i < group.getChildCount(); i++) {
+ final View child = group.getChildAt(i);
+ reverseParams(child.getLayoutParams(), child, isLayoutReverse);
+
+ // Recursively reverse all children
+ if (child instanceof ViewGroup) {
+ reverseGroup((ViewGroup) child, isLayoutReverse);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 7cd433a..384a6e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -148,16 +148,31 @@
boolean in = activityIn && mActivityEnabled && visible;
boolean out = activityOut && mActivityEnabled && visible;
- mWifiIconState.visible = visible;
- mWifiIconState.resId = statusIcon.icon;
- mWifiIconState.activityIn = in;
- mWifiIconState.activityOut = out;
- mWifiIconState.slot = mSlotWifi;
- mWifiIconState.airplaneSpacerVisible = mIsAirplaneMode;
- mWifiIconState.contentDescription = statusIcon.contentDescription;
+ WifiIconState newState = mWifiIconState.copy();
- if (mWifiIconState.visible && mWifiIconState.resId > 0) {
- mIconController.setSignalIcon(mSlotWifi, mWifiIconState.copy());
+ newState.visible = visible;
+ newState.resId = statusIcon.icon;
+ newState.activityIn = in;
+ newState.activityOut = out;
+ newState.slot = mSlotWifi;
+ newState.airplaneSpacerVisible = mIsAirplaneMode;
+ newState.contentDescription = statusIcon.contentDescription;
+
+ MobileIconState first = getFirstMobileState();
+ newState.signalSpacerVisible = first != null && first.typeId != 0;
+
+ updateWifiIconWithState(newState);
+ mWifiIconState = newState;
+ }
+
+ private void updateShowWifiSignalSpacer(WifiIconState state) {
+ MobileIconState first = getFirstMobileState();
+ state.signalSpacerVisible = first != null && first.typeId != 0;
+ }
+
+ private void updateWifiIconWithState(WifiIconState state) {
+ if (state.visible && state.resId > 0) {
+ mIconController.setSignalIcon(mSlotWifi, state);
mIconController.setIconVisibility(mSlotWifi, true);
} else {
mIconController.setIconVisibility(mSlotWifi, false);
@@ -173,6 +188,9 @@
return;
}
+ // Visibility of the data type indicator changed
+ boolean typeChanged = statusType != state.typeId && (statusType == 0 || state.typeId == 0);
+
state.visible = statusIcon.visible && !mBlockMobile;
state.strengthId = statusIcon.icon;
state.typeId = statusType;
@@ -184,6 +202,15 @@
// Always send a copy to maintain value type semantics
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
+
+ if (typeChanged) {
+ WifiIconState wifiCopy = mWifiIconState.copy();
+ updateShowWifiSignalSpacer(wifiCopy);
+ if (!Objects.equals(wifiCopy, mWifiIconState)) {
+ updateWifiIconWithState(wifiCopy);
+ mWifiIconState = wifiCopy;
+ }
+ }
}
private MobileIconState getState(int subId) {
@@ -196,6 +223,14 @@
return null;
}
+ private MobileIconState getFirstMobileState() {
+ if (mMobileStates.size() > 0) {
+ return mMobileStates.get(0);
+ }
+
+ return null;
+ }
+
/**
* It is expected that a call to setSubs will be immediately followed by setMobileDataIndicators
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 85cfde8..12b6f9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.policy;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
+
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -41,20 +44,14 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
-
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.NavigationBarCompat;
-import static android.view.KeyEvent.KEYCODE_HOME;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
-import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
-
public class KeyButtonView extends ImageView implements ButtonInterface {
private static final String TAG = KeyButtonView.class.getSimpleName();
@@ -119,6 +116,7 @@
mRipple = new KeyButtonRipple(context, this);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
setBackground(mRipple);
+ forceHasOverlappingRendering(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index a2b33fa..7410069 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -760,7 +760,9 @@
}
private void updateClippingToTopRoundedCorner() {
- Float clipStart = (float) mTopPadding + mAmbientState.getExpandAnimationTopChange();
+ Float clipStart = (float) mTopPadding
+ + mStackTranslation
+ + mAmbientState.getExpandAnimationTopChange();
Float clipEnd = clipStart + mCornerRadius;
boolean first = true;
for (int i = 0; i < getChildCount(); i++) {
@@ -769,8 +771,7 @@
continue;
}
float start = child.getTranslationY();
- float end = start + Math.max(child.getActualHeight() - child.getClipBottomAmount(),
- 0);
+ float end = start + child.getActualHeight();
boolean clip = clipStart > start && clipStart < end
|| clipEnd >= start && clipEnd <= end;
clip &= !(first && mOwnScrollY == 0);
@@ -3292,6 +3293,16 @@
if (!childWasSwipedOut) {
Rect clipBounds = child.getClipBounds();
childWasSwipedOut = clipBounds != null && clipBounds.height() == 0;
+
+ if (childWasSwipedOut && child instanceof ExpandableView) {
+ // Clean up any potential transient views if the child has already been swiped
+ // out, as we won't be animating it further (due to its height already being
+ // clipped to 0.
+ ViewGroup transientContainer = ((ExpandableView) child).getTransientContainer();
+ if (transientContainer != null) {
+ transientContainer.removeTransientView(child);
+ }
+ }
}
int animationType = childWasSwipedOut
? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e22a86e..c3f504f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2442,97 +2442,107 @@
}
}
+ // This is a no-op if it's called with a message designating a network that has
+ // already been destroyed, because its reference will not be found in the relevant
+ // maps.
private void handleAsyncChannelDisconnected(Message msg) {
NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
if (nai != null) {
- if (DBG) {
- log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
- }
- // A network agent has disconnected.
- // TODO - if we move the logic to the network agent (have them disconnect
- // because they lost all their requests or because their score isn't good)
- // then they would disconnect organically, report their new state and then
- // disconnect the channel.
- if (nai.networkInfo.isConnected()) {
- nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
- null, null);
- }
- final boolean wasDefault = isDefaultNetwork(nai);
- if (wasDefault) {
- mDefaultInetConditionPublished = 0;
- // Log default network disconnection before required book-keeping.
- // Let rematchAllNetworksAndRequests() below record a new default network event
- // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
- // whose timestamps tell how long it takes to recover a default network.
- long now = SystemClock.elapsedRealtime();
- metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
- }
- notifyIfacesChangedForNetworkStats();
- // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
- // by other networks that are already connected. Perhaps that can be done by
- // sending all CALLBACK_LOST messages (for requests, not listens) at the end
- // of rematchAllNetworksAndRequests
- notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
- mKeepaliveTracker.handleStopAllKeepalives(nai,
- ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
- for (String iface : nai.linkProperties.getAllInterfaceNames()) {
- // Disable wakeup packet monitoring for each interface.
- wakeupModifyInterface(iface, nai.networkCapabilities, false);
- }
- nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
- mNetworkAgentInfos.remove(msg.replyTo);
- nai.maybeStopClat();
- synchronized (mNetworkForNetId) {
- // Remove the NetworkAgent, but don't mark the netId as
- // available until we've told netd to delete it below.
- mNetworkForNetId.remove(nai.network.netId);
- }
- // Remove all previously satisfied requests.
- for (int i = 0; i < nai.numNetworkRequests(); i++) {
- NetworkRequest request = nai.requestAt(i);
- NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
- if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
- clearNetworkForRequest(request.requestId);
- sendUpdatedScoreToFactories(request, 0);
- }
- }
- nai.clearLingerState();
- if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
- removeDataActivityTracking(nai);
- notifyLockdownVpn(nai);
- ensureNetworkTransitionWakelock(nai.name());
- }
- mLegacyTypeTracker.remove(nai, wasDefault);
- if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- updateAllVpnsCapabilities();
- }
- rematchAllNetworksAndRequests(null, 0);
- mLingerMonitor.noteDisconnect(nai);
- if (nai.created) {
- // Tell netd to clean up the configuration for this network
- // (routing rules, DNS, etc).
- // This may be slow as it requires a lot of netd shelling out to ip and
- // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
- // after we've rematched networks with requests which should make a potential
- // fallback network the default or requested a new network from the
- // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
- // long time.
- try {
- mNetd.removeNetwork(nai.network.netId);
- } catch (Exception e) {
- loge("Exception removing network: " + e);
- }
- mDnsManager.removeNetwork(nai.network);
- }
- synchronized (mNetworkForNetId) {
- mNetIdInUse.delete(nai.network.netId);
- }
+ disconnectAndDestroyNetwork(nai);
} else {
NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
}
}
+ // Destroys a network, remove references to it from the internal state managed by
+ // ConnectivityService, free its interfaces and clean up.
+ // Must be called on the Handler thread.
+ private void disconnectAndDestroyNetwork(NetworkAgentInfo nai) {
+ if (DBG) {
+ log(nai.name() + " got DISCONNECTED, was satisfying " + nai.numNetworkRequests());
+ }
+ // A network agent has disconnected.
+ // TODO - if we move the logic to the network agent (have them disconnect
+ // because they lost all their requests or because their score isn't good)
+ // then they would disconnect organically, report their new state and then
+ // disconnect the channel.
+ if (nai.networkInfo.isConnected()) {
+ nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
+ null, null);
+ }
+ final boolean wasDefault = isDefaultNetwork(nai);
+ if (wasDefault) {
+ mDefaultInetConditionPublished = 0;
+ // Log default network disconnection before required book-keeping.
+ // Let rematchAllNetworksAndRequests() below record a new default network event
+ // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
+ // whose timestamps tell how long it takes to recover a default network.
+ long now = SystemClock.elapsedRealtime();
+ metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(now, null, nai);
+ }
+ notifyIfacesChangedForNetworkStats();
+ // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
+ // by other networks that are already connected. Perhaps that can be done by
+ // sending all CALLBACK_LOST messages (for requests, not listens) at the end
+ // of rematchAllNetworksAndRequests
+ notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
+ mKeepaliveTracker.handleStopAllKeepalives(nai,
+ ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
+ for (String iface : nai.linkProperties.getAllInterfaceNames()) {
+ // Disable wakeup packet monitoring for each interface.
+ wakeupModifyInterface(iface, nai.networkCapabilities, false);
+ }
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
+ mNetworkAgentInfos.remove(nai.messenger);
+ nai.maybeStopClat();
+ synchronized (mNetworkForNetId) {
+ // Remove the NetworkAgent, but don't mark the netId as
+ // available until we've told netd to delete it below.
+ mNetworkForNetId.remove(nai.network.netId);
+ }
+ // Remove all previously satisfied requests.
+ for (int i = 0; i < nai.numNetworkRequests(); i++) {
+ NetworkRequest request = nai.requestAt(i);
+ NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
+ if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
+ clearNetworkForRequest(request.requestId);
+ sendUpdatedScoreToFactories(request, 0);
+ }
+ }
+ nai.clearLingerState();
+ if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
+ removeDataActivityTracking(nai);
+ notifyLockdownVpn(nai);
+ ensureNetworkTransitionWakelock(nai.name());
+ }
+ mLegacyTypeTracker.remove(nai, wasDefault);
+ if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+ updateAllVpnsCapabilities();
+ }
+ rematchAllNetworksAndRequests(null, 0);
+ mLingerMonitor.noteDisconnect(nai);
+ if (nai.created) {
+ // Tell netd to clean up the configuration for this network
+ // (routing rules, DNS, etc).
+ // This may be slow as it requires a lot of netd shelling out to ip and
+ // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
+ // after we've rematched networks with requests which should make a potential
+ // fallback network the default or requested a new network from the
+ // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
+ // long time.
+ try {
+ mNetd.removeNetwork(nai.network.netId);
+ } catch (Exception e) {
+ loge("Exception removing network: " + e);
+ }
+ mDnsManager.removeNetwork(nai.network);
+ }
+ synchronized (mNetworkForNetId) {
+ mNetIdInUse.delete(nai.network.netId);
+ }
+ }
+
// If this method proves to be too slow then we can maintain a separate
// pendingIntent => NetworkRequestInfo map.
// This method assumes that every non-null PendingIntent maps to exactly 1 NetworkRequestInfo.
@@ -5618,6 +5628,7 @@
}
updateUids(networkAgent, networkAgent.networkCapabilities, null);
}
+ disconnectAndDestroyNetwork(networkAgent);
} else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) ||
state == NetworkInfo.State.SUSPENDED) {
// going into or coming out of SUSPEND: rescore and notify
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 67a16bd..c25f8ff 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -20548,7 +20548,7 @@
IPackageManager pm = AppGlobals.getPackageManager();
ApplicationInfo app = null;
try {
- app = pm.getApplicationInfo(packageName, 0, userId);
+ app = pm.getApplicationInfo(packageName, STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
// can't happen; package manager is process-local
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index afad0b1..7310fab 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2554,6 +2554,10 @@
final int displayId = mTmpOrderedDisplayIds.get(i);
// If a display is registered in WM, it must also be available in AM.
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+ if (display == null) {
+ // Looks like the display no longer exists in the system...
+ continue;
+ }
for (int j = display.getChildCount() - 1; j >= 0; --j) {
final ActivityStack stack = display.getChildAt(j);
if (ignoreCurrent && stack == currentFocus) {
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index d7057f4..2c9a494 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1310,10 +1310,10 @@
: ActivityManager.PROCESS_STATE_NONEXISTENT;
if (procState <= ActivityManager.PROCESS_STATE_TOP) {
- return ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
+ return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
}
if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- return ContentResolver.SYNC_EXEMPTION_ACTIVE;
+ return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
}
return ContentResolver.SYNC_EXEMPTION_NONE;
}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 33cf11b..0a640b8 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1656,7 +1656,7 @@
}
if (syncOperation.syncExemptionFlag
- == ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP) {
+ == ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
DeviceIdleController.LocalService dic =
LocalServices.getService(DeviceIdleController.LocalService.class);
if (dic != null) {
@@ -1668,6 +1668,15 @@
}
}
+ if (syncOperation.isAppStandbyExempted()) {
+ final UsageStatsManagerInternal usmi = LocalServices.getService(
+ UsageStatsManagerInternal.class);
+ if (usmi != null) {
+ usmi.reportExemptedSyncScheduled(syncOperation.owningPackage,
+ UserHandle.getUserId(syncOperation.owningUid));
+ }
+ }
+
getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
syncOperation.target.userId, syncOperation.wakeLockName());
}
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index d097563..25edf40 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -390,10 +390,10 @@
switch (syncExemptionFlag) {
case ContentResolver.SYNC_EXEMPTION_NONE:
break;
- case ContentResolver.SYNC_EXEMPTION_ACTIVE:
+ case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
sb.append(" STANDBY-EXEMPTED");
break;
- case ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP:
+ case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
sb.append(" STANDBY-EXEMPTED(TOP)");
break;
default:
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 6a343f8..11f0701 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -341,6 +341,7 @@
boolean initialization;
Bundle extras;
int reason;
+ int syncExemptionFlag;
}
public static class DayStats {
@@ -1142,6 +1143,7 @@
item.reason = op.reason;
item.extras = op.extras;
item.event = EVENT_START;
+ item.syncExemptionFlag = op.syncExemptionFlag;
mSyncHistory.add(0, item);
while (mSyncHistory.size() > MAX_HISTORY) {
mSyncHistory.remove(mSyncHistory.size()-1);
@@ -1262,6 +1264,20 @@
SyncManager.formatDurationHMS(event, elapsedTime);
event.append(" Reason=");
event.append(SyncOperation.reasonToString(null, item.reason));
+ if (item.syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE) {
+ event.append(" Exemption=");
+ switch (item.syncExemptionFlag) {
+ case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
+ event.append("fg");
+ break;
+ case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
+ event.append("top");
+ break;
+ default:
+ event.append(item.syncExemptionFlag);
+ break;
+ }
+ }
event.append(" Extras=");
SyncOperation.extrasToStringBuilder(item.extras, event);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9886a07..e810b1a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -367,6 +367,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
/**
* Keep track of all those APKs everywhere.
@@ -13942,6 +13943,43 @@
return false;
}
+ @Override
+ public boolean setSystemAppInstallState(String packageName, boolean installed, int userId) {
+ enforceSystemOrPhoneCaller("setSystemAppInstallState");
+ PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ // The target app should always be in system
+ if (pkgSetting == null || !pkgSetting.isSystem()) {
+ return false;
+ }
+ // Check if the install state is the same
+ if (pkgSetting.getInstalled(userId) == installed) {
+ return false;
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ if (installed) {
+ // install the app from uninstalled state
+ installExistingPackageAsUser(
+ packageName,
+ userId,
+ 0 /*installFlags*/,
+ PackageManager.INSTALL_REASON_DEVICE_SETUP);
+ return true;
+ }
+
+ // uninstall the app from installed state
+ deletePackageVersioned(
+ new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
+ new LegacyPackageDeleteObserver(null).getBinder(),
+ userId,
+ PackageManager.DELETE_SYSTEM_APP);
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
private void sendApplicationHiddenForUser(String packageName, PackageSetting pkgSetting,
int userId) {
final PackageRemovedInfo info = new PackageRemovedInfo(this);
@@ -14006,10 +14044,16 @@
@Override
public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
int installReason) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
- null);
- PackageSetting pkgSetting;
final int callingUid = Binder.getCallingUid();
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.INSTALL_EXISTING_PACKAGES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Neither user " + callingUid + " nor current process has "
+ + android.Manifest.permission.INSTALL_PACKAGES + ".");
+ }
+ PackageSetting pkgSetting;
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"installExistingPackage for user " + userId);
@@ -14258,28 +14302,50 @@
* @param packageName The package holding {@link Manifest.permission#SUSPEND_APPS} permission
* @param affectedUser The user for which the changes are taking place.
*/
- void unsuspendForSuspendingPackage(String packageName, int affectedUser) {
+ void unsuspendForSuspendingPackage(final String packageName, int affectedUser) {
final int[] userIds = (affectedUser == UserHandle.USER_ALL) ? sUserManager.getUserIds()
: new int[] {affectedUser};
for (int userId : userIds) {
- List<String> affectedPackages = new ArrayList<>();
- synchronized (mPackages) {
- for (PackageSetting ps : mSettings.mPackages.values()) {
- final PackageUserState pus = ps.readUserState(userId);
- if (pus.suspended && packageName.equals(pus.suspendingPackage)) {
- ps.setSuspended(false, null, null, null, null, userId);
- affectedPackages.add(ps.name);
- }
+ unsuspendForSuspendingPackages(packageName::equals, userId);
+ }
+ }
+
+ /**
+ * Immediately unsuspends any packages in the given users not suspended by the platform or root.
+ * To be called when a profile owner or a device owner is added.
+ *
+ * <p><b>Should not be used on a frequent code path</b> as it flushes state to disk
+ * synchronously
+ *
+ * @param userIds The users for which to unsuspend packages
+ */
+ void unsuspendForNonSystemSuspendingPackages(ArraySet<Integer> userIds) {
+ final int sz = userIds.size();
+ for (int i = 0; i < sz; i++) {
+ unsuspendForSuspendingPackages(
+ (suspendingPackage) -> !PLATFORM_PACKAGE_NAME.equals(suspendingPackage),
+ userIds.valueAt(i));
+ }
+ }
+
+ private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) {
+ final List<String> affectedPackages = new ArrayList<>();
+ synchronized (mPackages) {
+ for (PackageSetting ps : mSettings.mPackages.values()) {
+ final PackageUserState pus = ps.readUserState(userId);
+ if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
+ ps.setSuspended(false, null, null, null, null, userId);
+ affectedPackages.add(ps.name);
}
}
- if (!affectedPackages.isEmpty()) {
- final String[] packageArray = affectedPackages.toArray(
- new String[affectedPackages.size()]);
- sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
- sendPackagesSuspendedForUser(packageArray, userId, false, null);
- // Write package restrictions immediately to avoid an inconsistent state.
- mSettings.writePackageRestrictionsLPr(userId);
- }
+ }
+ if (!affectedPackages.isEmpty()) {
+ final String[] packageArray = affectedPackages.toArray(
+ new String[affectedPackages.size()]);
+ sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
+ sendPackagesSuspendedForUser(packageArray, userId, false, null);
+ // Write package restrictions immediately to avoid an inconsistent state.
+ mSettings.writePackageRestrictionsLPr(userId);
}
}
@@ -23977,6 +24043,18 @@
SparseArray<String> profileOwnerPackages) {
mProtectedPackages.setDeviceAndProfileOwnerPackages(
deviceOwnerUserId, deviceOwnerPackage, profileOwnerPackages);
+
+ final ArraySet<Integer> usersWithPoOrDo = new ArraySet<>();
+ if (deviceOwnerPackage != null) {
+ usersWithPoOrDo.add(deviceOwnerUserId);
+ }
+ final int sz = profileOwnerPackages.size();
+ for (int i = 0; i < sz; i++) {
+ if (profileOwnerPackages.valueAt(i) != null) {
+ usersWithPoOrDo.add(profileOwnerPackages.keyAt(i));
+ }
+ }
+ unsuspendForNonSystemSuspendingPackages(usersWithPoOrDo);
}
@Override
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 2886126..547ab0e 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -557,7 +557,7 @@
if (cropFile != null) {
Bitmap bitmap = BitmapFactory.decodeFile(cropFile);
if (bitmap != null) {
- colors = WallpaperColors.fromBitmap(bitmap, true /* computeHints */);
+ colors = WallpaperColors.fromBitmap(bitmap);
bitmap.recycle();
}
}
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 2ac9df9..a8efe81 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -70,7 +70,7 @@
<uses-sdk android:minSdkVersion="1"
android:targetSdkVersion="26"/>
- <application>
+ <application android:testOnly="true">
<uses-library android:name="android.test.runner" />
<service android:name="com.android.server.accounts.TestAccountType1AuthenticatorService"
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 8f989df..5ac68d4 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="test-suite-tag" value="apct-instrumentation" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
<option name="test-file-name" value="FrameworksServicesTests.apk" />
<option name="test-file-name" value="JobTestApp.apk" />
<option name="test-file-name" value="ConnTestApp.apk" />
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index b8922eb..c186e48 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.app.AppGlobals;
import android.content.BroadcastReceiver;
@@ -59,6 +60,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
@@ -97,6 +99,9 @@
private AppCommunicationReceiver mAppCommsReceiver;
private StubbedCallback mTestCallback;
private UiDevice mUiDevice;
+ private ComponentName mDeviceAdminComponent;
+ private boolean mPoSet;
+ private boolean mDoSet;
private static final class AppCommunicationReceiver extends BroadcastReceiver {
private Context context;
@@ -163,6 +168,8 @@
mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
mReceiverHandler = new Handler(Looper.getMainLooper());
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mDeviceAdminComponent = new ComponentName(mContext,
+ "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
IPackageManager ipm = AppGlobals.getPackageManager();
try {
// Otherwise implicit broadcasts will not be delivered.
@@ -469,12 +476,83 @@
TEST_APP_PACKAGE_NAME, receivedPackageName);
}
+ private boolean setProfileOwner() throws IOException {
+ final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ return mPoSet = result.trim().startsWith("Success");
+ }
+
+ private boolean setDeviceOwner() throws IOException {
+ final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ return mDoSet = result.trim().startsWith("Success");
+ }
+
+ private void removeProfileOrDeviceOwner() throws IOException {
+ if (mPoSet || mDoSet) {
+ mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
+ + mDeviceAdminComponent.flattenToString());
+ mPoSet = mDoSet = false;
+ }
+ }
+
+ @Test
+ public void testCannotSuspendWhenProfileOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ assertTrue("Profile-owner could not be set", setProfileOwner());
+ try {
+ suspendTestPackage(null, null, null);
+ fail("Suspend succeeded. Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uex) {
+ }
+ }
+
+ @Test
+ public void testCannotSuspendWhenDeviceOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ assertTrue("Device-owner could not be set", setDeviceOwner());
+ try {
+ suspendTestPackage(null, null, null);
+ fail("Suspend succeeded. Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException uex) {
+ }
+ }
+
+ @Test
+ public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ mAppCommsReceiver.drainPendingBroadcasts();
+ suspendTestPackage(null, null, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
+ assertTrue("Device-owner could not be set", setDeviceOwner());
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
+ }
+
+ @Test
+ public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
+ assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
+ mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ mAppCommsReceiver.drainPendingBroadcasts();
+ suspendTestPackage(null, null, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
+ assertTrue("Profile-owner could not be set", setProfileOwner());
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
+ }
+
@After
- public void tearDown() {
+ public void tearDown() throws IOException {
mAppCommsReceiver.unregister();
if (mTestCallback != null) {
mLauncherApps.unregisterCallback(mTestCallback);
}
+ removeProfileOrDeviceOwner();
mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
.setPackage(TEST_APP_PACKAGE_NAME));
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index dee2556..8461166 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -218,6 +218,11 @@
+ "stable_charging_threshold=" + STABLE_CHARGING_THRESHOLD;
}
+ @Override
+ public boolean isDeviceIdleMode() {
+ return false;
+ }
+
// Internal methods
void setDisplayOn(boolean on) {
diff --git a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
index 4d99b32..9c010a0 100644
--- a/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/wallpaper/WallpaperServiceTests.java
@@ -20,8 +20,6 @@
import static org.junit.Assert.assertTrue;
import android.app.WallpaperColors;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -87,17 +85,4 @@
assertEquals("OnComputeColors should have been deferred.",
0, eventCountdown.getCount());
}
-
- @Test
- public void testFromDrawableTest_doesntComputeHints() {
- WallpaperColors wallpaperColors = WallpaperColors.fromDrawable(
- new ColorDrawable(Color.BLACK));
- assertEquals("WallpaperColors should not support dark theme.", 0,
- wallpaperColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME);
-
- wallpaperColors = WallpaperColors.fromDrawable(
- new ColorDrawable(Color.WHITE));
- assertEquals("WallpaperColors should not support dark text.", 0,
- wallpaperColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT);
- }
}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3378897..9c62700 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -24,6 +24,8 @@
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
@@ -194,8 +196,9 @@
static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
/** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
- static final int MSG_REPORT_EXEMPTED_SYNC_START = 12;
- static final int MSG_UPDATE_STABLE_CHARGING= 13;
+ static final int MSG_REPORT_EXEMPTED_SYNC_SCHEDULED = 12;
+ static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
+ static final int MSG_UPDATE_STABLE_CHARGING= 14;
long mCheckIdleIntervalMillis;
long mAppIdleParoleIntervalMillis;
@@ -213,8 +216,20 @@
long mPredictionTimeoutMillis;
/** Maximum time a sync adapter associated with a CP should keep the buckets elevated. */
long mSyncAdapterTimeoutMillis;
- /** Maximum time an exempted sync should keep the buckets elevated. */
- long mExemptedSyncAdapterTimeoutMillis;
+ /**
+ * Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
+ * non-doze
+ */
+ long mExemptedSyncScheduledNonDozeTimeoutMillis;
+ /**
+ * Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
+ * doze
+ */
+ long mExemptedSyncScheduledDozeTimeoutMillis;
+ /**
+ * Maximum time an exempted sync should keep the buckets elevated, when sync is started.
+ */
+ long mExemptedSyncStartTimeoutMillis;
/** Maximum time a system interaction should keep the buckets elevated. */
long mSystemInteractionTimeoutMillis;
/** The length of time phone must be charging before considered stable enough to run jobs */
@@ -393,6 +408,37 @@
}
}
+ void reportExemptedSyncScheduled(String packageName, int userId) {
+ if (!mAppIdleEnabled) return;
+
+ final int bucketToPromote;
+ final int usageReason;
+ final long durationMillis;
+
+ if (!mInjector.isDeviceIdleMode()) {
+ // Not dozing.
+ bucketToPromote = STANDBY_BUCKET_ACTIVE;
+ usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
+ durationMillis = mExemptedSyncScheduledNonDozeTimeoutMillis;
+ } else {
+ // Dozing.
+ bucketToPromote = STANDBY_BUCKET_WORKING_SET;
+ usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
+ durationMillis = mExemptedSyncScheduledDozeTimeoutMillis;
+ }
+
+ final long elapsedRealtime = mInjector.elapsedRealtime();
+
+ synchronized (mAppIdleLock) {
+ AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
+ bucketToPromote, usageReason,
+ 0,
+ elapsedRealtime + durationMillis);
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ appUsage.currentBucket, appUsage.bucketingReason, false);
+ }
+ }
+
void reportExemptedSyncStart(String packageName, int userId) {
if (!mAppIdleEnabled) return;
@@ -402,7 +448,7 @@
AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_EXEMPTED_SYNC_START,
0,
- elapsedRealtime + mExemptedSyncAdapterTimeoutMillis);
+ elapsedRealtime + mExemptedSyncStartTimeoutMillis);
maybeInformListeners(packageName, userId, elapsedRealtime,
appUsage.currentBucket, appUsage.bucketingReason, false);
}
@@ -1365,6 +1411,11 @@
.sendToTarget();
}
+ void postReportExemptedSyncScheduled(String packageName, int userId) {
+ mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_SCHEDULED, userId, 0, packageName)
+ .sendToTarget();
+ }
+
void postReportExemptedSyncStart(String packageName, int userId) {
mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_START, userId, 0, packageName)
.sendToTarget();
@@ -1401,6 +1452,16 @@
TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
pw.println();
+ pw.print(" mExemptedSyncScheduledNonDozeTimeoutMillis=");
+ TimeUtils.formatDuration(mExemptedSyncScheduledNonDozeTimeoutMillis, pw);
+ pw.println();
+ pw.print(" mExemptedSyncScheduledDozeTimeoutMillis=");
+ TimeUtils.formatDuration(mExemptedSyncScheduledDozeTimeoutMillis, pw);
+ pw.println();
+ pw.print(" mExemptedSyncStartTimeoutMillis=");
+ TimeUtils.formatDuration(mExemptedSyncStartTimeoutMillis, pw);
+ pw.println();
+
pw.println();
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
@@ -1429,6 +1490,7 @@
private IBatteryStats mBatteryStats;
private PackageManagerInternal mPackageManagerInternal;
private DisplayManager mDisplayManager;
+ private PowerManager mPowerManager;
int mBootPhase;
Injector(Context context, Looper looper) {
@@ -1453,6 +1515,7 @@
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mDisplayManager = (DisplayManager) mContext.getSystemService(
Context.DISPLAY_SERVICE);
+ mPowerManager = mContext.getSystemService(PowerManager.class);
}
mBootPhase = phase;
}
@@ -1532,6 +1595,11 @@
return Global.getString(mContext.getContentResolver(),
Global.APP_IDLE_CONSTANTS);
}
+
+ /** Whether the device is in doze or not. */
+ public boolean isDeviceIdleMode() {
+ return mPowerManager.isDeviceIdleMode();
+ }
}
class AppStandbyHandler extends Handler {
@@ -1595,6 +1663,10 @@
mInjector.elapsedRealtime());
break;
+ case MSG_REPORT_EXEMPTED_SYNC_SCHEDULED:
+ reportExemptedSyncScheduled((String) msg.obj, msg.arg1);
+ break;
+
case MSG_REPORT_EXEMPTED_SYNC_START:
reportExemptedSyncStart((String) msg.obj, msg.arg1);
break;
@@ -1684,7 +1756,12 @@
"system_update_usage_duration";
private static final String KEY_PREDICTION_TIMEOUT = "prediction_timeout";
private static final String KEY_SYNC_ADAPTER_HOLD_DURATION = "sync_adapter_duration";
- private static final String KEY_EXEMPTED_SYNC_HOLD_DURATION = "exempted_sync_duration";
+ private static final String KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION
+ = "exempted_sync_scheduled_nd_duration";
+ private static final String KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION
+ = "exempted_sync_scheduled_d_duration";
+ private static final String KEY_EXEMPTED_SYNC_START_HOLD_DURATION
+ = "exempted_sync_start_duration";
private static final String KEY_SYSTEM_INTERACTION_HOLD_DURATION =
"system_interaction_duration";
private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
@@ -1693,7 +1770,9 @@
public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
public static final long DEFAULT_SYSTEM_INTERACTION_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_SYNC_ADAPTER_TIMEOUT = 10 * ONE_MINUTE;
- public static final long DEFAULT_EXEMPTED_SYNC_TIMEOUT = 10 * ONE_MINUTE;
+ public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT = 10 * ONE_MINUTE;
+ public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
+ public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1778,9 +1857,22 @@
mSyncAdapterTimeoutMillis = mParser.getDurationMillis
(KEY_SYNC_ADAPTER_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYNC_ADAPTER_TIMEOUT);
- mExemptedSyncAdapterTimeoutMillis = mParser.getDurationMillis
- (KEY_EXEMPTED_SYNC_HOLD_DURATION,
- COMPRESS_TIME ? ONE_MINUTE : DEFAULT_EXEMPTED_SYNC_TIMEOUT);
+
+ mExemptedSyncScheduledNonDozeTimeoutMillis = mParser.getDurationMillis
+ (KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION,
+ COMPRESS_TIME ? (ONE_MINUTE / 2)
+ : DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT);
+
+ mExemptedSyncScheduledDozeTimeoutMillis = mParser.getDurationMillis
+ (KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
+ COMPRESS_TIME ? ONE_MINUTE
+ : DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT);
+
+ mExemptedSyncStartTimeoutMillis = mParser.getDurationMillis
+ (KEY_EXEMPTED_SYNC_START_HOLD_DURATION,
+ COMPRESS_TIME ? ONE_MINUTE
+ : DEFAULT_EXEMPTED_SYNC_START_TIMEOUT);
+
mSystemInteractionTimeoutMillis = mParser.getDurationMillis
(KEY_SYSTEM_INTERACTION_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYSTEM_INTERACTION_TIMEOUT);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 6311127a..a7d3f78 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1371,6 +1371,11 @@
}
@Override
+ public void reportExemptedSyncScheduled(String packageName, int userId) {
+ mAppStandby.postReportExemptedSyncScheduled(packageName, userId);
+ }
+
+ @Override
public void reportExemptedSyncStart(String packageName, int userId) {
mAppStandby.postReportExemptedSyncStart(packageName, userId);
}
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index bcad554..676684c 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -152,9 +152,14 @@
&& (ai.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
+ packageManager.setSystemAppInstallState(
+ packageName,
+ true /*installed*/,
+ userId);
packageManager.setApplicationEnabledSetting(
packageName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
@@ -170,9 +175,14 @@
if (associatedApp.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
Slog.i(TAG, "Update associated state(" + associatedApp.packageName
+ "): ENABLED for user " + userId);
+ packageManager.setSystemAppInstallState(
+ associatedApp.packageName,
+ true /*installed*/,
+ userId);
packageManager.setApplicationEnabledSetting(
associatedApp.packageName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
@@ -190,15 +200,14 @@
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
&& ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
Slog.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setApplicationEnabledSetting(
+ packageManager.setSystemAppInstallState(
packageName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
- 0,
- userId,
- callingPackage);
+ false /*installed*/,
+ userId);
}
// Also disable any associated apps for this carrier app if this is the first
@@ -213,13 +222,10 @@
Slog.i(TAG,
"Update associated state(" + associatedApp.packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setApplicationEnabledSetting(
+ packageManager.setSystemAppInstallState(
associatedApp.packageName,
- PackageManager
- .COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
- 0,
- userId,
- callingPackage);
+ false /*installed*/,
+ userId);
}
}
}
@@ -357,7 +363,8 @@
String packageName) {
try {
ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, userId);
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS, userId);
if (ai != null && ai.isSystemApp()) {
return ai;
}