Merge "Add some telephony API to light grey." 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/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/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 105cd38..0257891 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -70,7 +70,7 @@
assertNotCalled();
mCalled = true;
try {
- mCallback.onFailure(message);
+ mCallback.onFailure(mRequestId, message);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 2bb3e9a..1bad1d7 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -28,5 +28,5 @@
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
void onSuccess(in FillResponse response);
- void onFailure(CharSequence message);
+ void onFailure(int requestId, CharSequence message);
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 4c7dc11..5305c1a 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1899,10 +1899,17 @@
}
private LogMaker newLog(int category) {
- return new LogMaker(category)
- .setPackageName(mContext.getPackageName())
+ final LogMaker log = new LogMaker(category)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE,
isCompatibilityModeEnabledLocked() ? 1 : 0);
+ final AutofillClient client = getClient();
+ if (client == null) {
+ // Client should never be null here, but it doesn't hurt to check...
+ log.setPackageName(mContext.getPackageName());
+ } else {
+ log.setComponentName(client.autofillClientGetComponentName());
+ }
+ return log;
}
/**
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/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/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/car_add_circle_round.xml b/packages/SystemUI/res/drawable/car_add_circle_round.xml
index 5cf0c31..13c7dd1 100644
--- a/packages/SystemUI/res/drawable/car_add_circle_round.xml
+++ b/packages/SystemUI/res/drawable/car_add_circle_round.xml
@@ -1,4 +1,18 @@
<?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.
+-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
diff --git a/packages/SystemUI/res/drawable/car_ic_add_white.xml b/packages/SystemUI/res/drawable/car_ic_add_white.xml
index f24771d..d681860 100644
--- a/packages/SystemUI/res/drawable/car_ic_add_white.xml
+++ b/packages/SystemUI/res/drawable/car_ic_add_white.xml
@@ -1,3 +1,17 @@
+<!-- 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.
+-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="@dimen/car_touch_target_size"
android:height="@dimen/car_touch_target_size"
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 907be01..2cd7883 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -21,10 +21,12 @@
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="M12,4c-0.06,0 -0.12,0.01 -0.18,0.01l1.09,-1.09L11.5,1.5L8,5l3.5,3.5l1.41,-1.41l-1.08,-1.08C11.89,6.01 11.95,6 12,6c3.31,0 6,2.69 6,6c0,1.7 -0.71,3.23 -1.85,4.32l1.41,1.41C19.06,16.28 20,14.25 20,12C20,7.59 16.41,4 12,4zM16,19l-3.5,3.5l-1.41,-1.41l1.1,-1.1C12.13,19.98 12.06,20 12,20c-4.41,0 -8,-3.59 -8,-8c0,-2.25 0.94,-4.28 2.43,-5.73l1.41,1.41C6.71,8.77 6,10.3 6,12c0,3.31 2.69,6 6,6c0.05,0 0.11,-0.01 0.16,-0.01l-1.07,-1.07l1.41,-1.41L16,19z"/>
+ 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/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/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 82869ca..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>
@@ -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/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 52e1c16..24875d7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -58,7 +58,7 @@
import androidx.slice.Slice;
import androidx.slice.SliceItem;
-import androidx.slice.SliceManager;
+import androidx.slice.SliceViewManager;
import androidx.slice.core.SliceQuery;
import androidx.slice.widget.ListContent;
import androidx.slice.widget.RowContent;
@@ -373,7 +373,7 @@
}
public void refresh() {
- Slice slice = SliceManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
+ Slice slice = SliceViewManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
onChanged(slice);
}
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 fec76f2..086c87b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -173,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);
}
@@ -188,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);
}
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/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/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/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d064105..cec4538 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3986,27 +3986,42 @@
// OS: O
APP_TRANSITION_IS_EPHEMERAL = 905;
- // An autofill session was started
+ // An autofill session was started.
+ // OS: O
// Package: Package of app that is autofilled
// NOTE: starting on OS MR1, it also added the following field:
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// NOTE: starting on OS P, it also added the following field:
- // Tag FIELD_FLAGS - Flags used to start the session
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFIL_FLAGS - Flags used to start the session
// Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SESSION_STARTED = 906;
// An autofill request was processed by a service
- // Type TYPE_SUCCESS: The request succeeded
- // Type TYPE_FAILURE: The request failed
+ // Type TYPE_SUCCESS: service called FillCalback.onSuccess()
+ // Type TYPE_FAILURE: service called FillCallback.onFailure()
// Package: Package of app that is autofilled
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned in the response, or -1 if
- // the service returned a null response.
- // NOTE: starting on OS P, it also added:
- // Type TYPE_CLOSE: Service returned a null response.
+ // the service returned a null response
+ // NOTE: starting on OS P, it also added the following fields:
+ // TYPE_CLOSE: request timed out before service called a FillCallback method
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_REQUEST_ORDINAL: sequence number of the request inside a session; starts
+ // with 1.
+ // Tag FIELD_AUTOFILL_FLAGS: flags used to request autofill
+ // Tag FIELD_AUTOFILL_DURATION: how long it took (in ms) to show the autofill UI after a field
+ // was focused.
+ // Tag FIELD_AUTOFILL_AUTHENTICATION_STATUS: status of authenticated datasets or responses.
// Tag FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS: if service requested field classification,
- // number of entries field ids in the request.
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // number of entries field ids in the request.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: Prior to P, some of the fields above were logged by 5 different metrics:
+ // - AUTOFILL_UI_LATENCY
+ // - AUTOFILL_AUTHENTICATED;
+ // - AUTOFILL_DATASET_AUTHENTICATED
+ // - AUTOFILL_INVALID_AUTHENTICATION
+ // - AUTOFILL_INVALID_DATASET_AUTHENTICATION
AUTOFILL_REQUEST = 907;
// Tag of a field for a package of an autofill service
@@ -4023,9 +4038,10 @@
// Package: Package of app that was autofilled
// Tag FIELD_AUTOFILL_FILTERTEXT_LEN: The length of the filter text
// Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets shown
- // NOTE: starting on OS P, it also added the following field:
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_FILL_UI = 910;
// Tag of a field for the length of the filter text
@@ -4034,16 +4050,16 @@
// An autofill authentication succeeded
// Package: Package of app that was autofilled
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
AUTOFILL_AUTHENTICATED = 912;
// An activity was autofilled and all values could be applied
// Package: Package of app that is autofilled
// Tag FIELD_AUTOFILL_NUM_VALUES: Number of values that were suggested to be autofilled
// Tag FIELD_AUTOFILL_NUM_VIEWS_FILLED: Number of views that could be filled
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_DATASET_APPLIED = 913;
// Tag of a field for the number values to be filled in
@@ -4058,28 +4074,34 @@
// Type TYPE_ACTION: data was saved
// Package: Package of app that was autofilled
// Tag FIELD_AUTOFILL_NUM_IDS: The number of ids that are saved
- // NOTE: starting on OS P, it also added the following field:
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_UI = 916;
// Tag of a field for the number of saveable ids
FIELD_AUTOFILL_NUM_IDS = 917;
- // ACTION: An autofill service was reqiested to save data
+ // ACTION: An autofill service was requested to save data
// Type TYPE_SUCCESS: The request succeeded right away
// Type TYPE_OPEN: The request succeeded but the service launched an IntentSender
// Type TYPE_FAILURE: The request failed
// Package: Package of app that was autofilled
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_DATA_SAVE_REQUEST = 918;
// An auto-fill session was finished
+ // OS: O
// Package: Package of app that was autofilled
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_NUMBER_REQUESTS: number of requests made to the service (each request
+ // is logged by a separate AUTOFILL_REQUEST metric)
AUTOFILL_SESSION_FINISHED = 919;
// meta-event: a reader has checkpointed the log here.
@@ -4206,7 +4228,7 @@
// Tag FIELD_AUTOFILL_SERVICE: Package of the autofill service that processed the request
// TAG FIELD_AUTOFILL_FORGED_COMPONENT_NAME: Component name being forged
// NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_FORGED_COMPONENT_ATTEMPT = 948;
// FIELD - The component that an app tried tro forged.
@@ -4664,8 +4686,9 @@
// OS: O MR
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_PREVIOUS_LENGTH: the previous length of the value
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_VALUE_RESET = 1124;
// Tag of AUTOFILL_VALUE_RESET
@@ -4675,25 +4698,21 @@
// An autofill dataset authentication succeeded
// Package: Package of app that was autofilled
// OS: O MR
- // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
AUTOFILL_DATASET_AUTHENTICATED = 1126;
// An autofill service provided an invalid dataset authentication
// Package: Package of app that was autofilled
// OS: O MR
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
AUTOFILL_INVALID_DATASET_AUTHENTICATION = 1127;
// An autofill service provided an invalid authentication extra
// Package: Package of app that was autofilled
// OS: O MR
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
AUTOFILL_INVALID_AUTHENTICATION = 1128;
// An autofill service used a custom description (using RemoteViews) in the autofill save UI
@@ -4701,8 +4720,9 @@
// OS: O MR
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_CUSTOM_DESCRIPTION = 1129;
// FIELD - Type of save object passed by the service when the Save UI is shown
@@ -4714,8 +4734,9 @@
// OS: O MR
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_CUSTOM_SUBTITLE = 1131;
// User tapped a link in the custom description of the autofill save UI provided by an autofill service
@@ -4726,8 +4747,9 @@
// Type TYPE_FAILURE: The link could not launc an activity
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_LINK_TAPPED = 1132;
// Result of the validation on save when an autofill service provided a validator
@@ -4738,8 +4760,9 @@
// Type TYPE_DISMISS: The validation failed
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_VALIDATION = 1133;
// Result of an operation in the autofill save UI after the user tapped a link in the custom description
@@ -4749,8 +4772,9 @@
// Type TYPE_OPEN: The autofill save UI was restored
// Type TYPE_DISMISS: The autofill save UI was destroyed
// Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // NOTE: starting on OS P, it also added the following fields:
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134;
// Autofill service called API that disables itself
@@ -4758,13 +4782,12 @@
// OS: O MR
AUTOFILL_SERVICE_DISABLED_SELF = 1135;
+ // DEPRECATED - on P it was merged with AUTOFILL_REQUEST
// Reports how long it took to show the autofill UI after a field was focused
// Tag FIELD_AUTOFILL_DURATION: Duration in ms
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Package: Package of the autofill service
// OS: O MR
- // NOTE: starting on OS P, it also added the following field:
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_UI_LATENCY = 1136;
// Action: the snooze leave-behind was shown after the user clicked the snooze icon
@@ -4931,15 +4954,17 @@
// An autofill service explicitly defined which view should commit the autofill context
// Package: Package of app that is autofilled
// OS: P
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION = 1228;
// The autofill context was commited when the user clicked a view explicitly marked by the
// service as committing it
// Package: Package of app that is autofilled
// OS: P
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SAVE_EXPLICITLY_TRIGGERED = 1229;
// OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling
@@ -4952,7 +4977,7 @@
// OS: P
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_DURATION: duration (in ms) that autofill will be disabled
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SERVICE_DISABLED_APP = 1231;
// An autofill service asked to disable autofill for a given activity.
@@ -4961,7 +4986,7 @@
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_CLASS_NAME: Class name of the activity that is being disabled for autofill
// Tag FIELD_AUTOFILL_DURATION: duration (in ms) that autofill will be disabled
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_SERVICE_DISABLED_ACTIVITY = 1232;
// ACTION: Stop an app and turn on background check
@@ -5171,9 +5196,10 @@
// Package: Package of app that is autofilled
// Counter: number of matches found
// OS: P
+ // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
// Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
// Tag FIELD_AUTOFILL_MATCH_SCORE: Average score of the matches, in the range of 0 to 100
- // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+ // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
AUTOFILL_FIELD_CLASSIFICATION_MATCHES = 1273;
// Tag used to report autofill field classification scores
@@ -5840,6 +5866,7 @@
ACTION_STORAGE_MIGRATE_LATER = 1413;
// Tag used to report whether an activity is being autofilled on compatibility mode.
+ // OS: P
FIELD_AUTOFILL_COMPAT_MODE = 1414;
// OPEN: Settings > Sound > Switch a2dp devices dialog
@@ -6045,6 +6072,28 @@
// OS: P
ACTION_BATTERY_CAUSED_SHUTDOWN = 1451;
+ // FIELD: Flags used on autofill-related metrics
+ // OS: P
+ FIELD_AUTOFILL_FLAGS = 1452;
+
+ // Tag used when the service returned an authenticated dataset or response.
+ // Used to replace the following individual metrics, which now are logged as the value of this
+ // field in the AUTOFILL_REQUEST metric:
+ // - AUTOFILL_AUTHENTICATED;
+ // - AUTOFILL_DATASET_AUTHENTICATED
+ // - AUTOFILL_INVALID_AUTHENTICATION
+ // - AUTOFILL_INVALID_DATASET_AUTHENTICATION
+ // OS: P
+ FIELD_AUTOFILL_AUTHENTICATION_STATUS = 1453;
+
+ // FIELD: Index of the autofill request inside of a session.
+ // OS: P
+ FIELD_AUTOFILL_REQUEST_ORDINAL = 1454;
+
+ // FIELD: Number of requests made to an autofill service during a session.
+ // OS: P
+ FIELD_AUTOFILL_NUMBER_REQUESTS = 1455;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index d97253e..3020e00 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -780,10 +780,10 @@
@Nullable ArrayList<String> changedDatasetIds,
@Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
- @NonNull String appPackageName, boolean compatMode) {
+ @NonNull ComponentName appComponentName, boolean compatMode) {
logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets,
changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
- manuallyFilledDatasetIds, null, null, appPackageName, compatMode);
+ manuallyFilledDatasetIds, null, null, appComponentName, compatMode);
}
@GuardedBy("mLock")
@@ -796,7 +796,7 @@
@Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
@Nullable ArrayList<AutofillId> detectedFieldIdsList,
@Nullable ArrayList<FieldClassification> detectedFieldClassificationsList,
- @NonNull String appPackageName, boolean compatMode) {
+ @NonNull ComponentName appComponentName, boolean compatMode) {
if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
if (sVerbose) {
Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId
@@ -807,6 +807,7 @@
+ ", manuallyFilledFieldIds=" + manuallyFilledFieldIds
+ ", detectedFieldIds=" + detectedFieldIdsList
+ ", detectedFieldClassifications=" + detectedFieldClassificationsList
+ + ", appComponentName=" + appComponentName.toShortString()
+ ", compatMode=" + compatMode);
}
AutofillId[] detectedFieldsIds = null;
@@ -834,7 +835,7 @@
final int averageScore = (int) ((totalScore * 100) / totalSize);
mMetricsLogger.write(Helper
.newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES,
- appPackageName, getServicePackageName(), compatMode)
+ appComponentName, getServicePackageName(), compatMode)
.setCounterValue(numberFields)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE,
averageScore));
@@ -889,9 +890,11 @@
}
mUserData = userData;
// Log it
- int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
- mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED,
- getServicePackageName(), null)
+ final int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
+ // NOTE: contrary to most metrics, the service name is logged as the main package name
+ // here, not as MetricsEvent.FIELD_AUTOFILL_SERVICE
+ mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED)
+ .setPackageName(getServicePackageName())
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, numberFields));
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index f781013..ca8843d 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
+import android.content.ComponentName;
import android.metrics.LogMaker;
import android.service.autofill.Dataset;
import android.util.ArrayMap;
@@ -109,20 +110,27 @@
}
@NonNull
- public static LogMaker newLogMaker(int category, String packageName,
- String servicePackageName) {
- final LogMaker log = new LogMaker(category).setPackageName(packageName);
- if (servicePackageName != null) {
- log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ private static LogMaker newLogMaker(int category, @NonNull String servicePackageName,
+ boolean compatMode) {
+ final LogMaker log = new LogMaker(category)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+ if (compatMode) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
}
return log;
}
@NonNull
- public static LogMaker newLogMaker(int category, String packageName,
- String servicePackageName, boolean compatMode) {
- return newLogMaker(category, packageName, servicePackageName)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, compatMode ? 1 : 0);
+ public static LogMaker newLogMaker(int category, @NonNull String packageName,
+ @NonNull String servicePackageName, boolean compatMode) {
+ return newLogMaker(category, servicePackageName, compatMode).setPackageName(packageName);
+ }
+
+ @NonNull
+ public static LogMaker newLogMaker(int category, @NonNull ComponentName componentName,
+ @NonNull String servicePackageName, boolean compatMode) {
+ return newLogMaker(category, servicePackageName, compatMode)
+ .setComponentName(componentName);
}
public static void printlnRedactedText(@NonNull PrintWriter pw, @Nullable CharSequence text) {
@@ -193,6 +201,18 @@
return urlBarNode;
}
+ /**
+ * Gets the value of a metric tag, or {@code 0} if not found or NaN.
+ */
+ static int getNumericValue(@NonNull LogMaker log, int tag) {
+ final Object value = log.getTaggedData(tag);
+ if (!(value instanceof Number)) {
+ return 0;
+ } else {
+ return ((Number) value).intValue();
+ }
+ }
+
private interface ViewNodeFilter {
boolean matches(ViewNode node);
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 4ded3fe..3e932e8 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -99,12 +99,14 @@
private PendingRequest mPendingRequest;
public interface FillServiceCallbacks {
- void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response,
+ void onFillRequestSuccess(int requestId, @Nullable FillResponse response,
+ @NonNull String servicePackageName, int requestFlags);
+ void onFillRequestFailure(int requestId, @Nullable CharSequence message,
@NonNull String servicePackageName);
- void onFillRequestFailure(@Nullable CharSequence message,
- @NonNull String servicePackageName);
+ void onFillRequestTimeout(int requestId, @NonNull String servicePackageName);
void onSaveRequestSuccess(@NonNull String servicePackageName,
@Nullable IntentSender intentSender);
+ // TODO(b/80093094): add timeout here too?
void onSaveRequestFailure(@Nullable CharSequence message,
@NonNull String servicePackageName);
void onServiceDied(RemoteFillService service);
@@ -301,21 +303,31 @@
mContext.unbindService(mServiceConnection);
}
- private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, int requestFlags,
- FillResponse response) {
+ private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest,
+ @Nullable FillResponse response, int requestFlags) {
mHandler.post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onFillRequestSuccess(requestFlags, response,
+ mCallbacks.onFillRequestSuccess(pendingRequest.mRequest.getId(), response,
+ mComponentName.getPackageName(), requestFlags);
+ }
+ });
+ }
+
+ private void dispatchOnFillRequestFailure(@NonNull PendingFillRequest pendingRequest,
+ @Nullable CharSequence message) {
+ mHandler.post(() -> {
+ if (handleResponseCallbackCommon(pendingRequest)) {
+ mCallbacks.onFillRequestFailure(pendingRequest.mRequest.getId(), message,
mComponentName.getPackageName());
}
});
}
- private void dispatchOnFillRequestFailure(PendingRequest pendingRequest,
- @Nullable CharSequence message) {
+ private void dispatchOnFillRequestTimeout(@NonNull PendingFillRequest pendingRequest) {
mHandler.post(() -> {
if (handleResponseCallbackCommon(pendingRequest)) {
- mCallbacks.onFillRequestFailure(message, mComponentName.getPackageName());
+ mCallbacks.onFillRequestTimeout(pendingRequest.mRequest.getId(),
+ mComponentName.getPackageName());
}
});
}
@@ -538,18 +550,18 @@
final RemoteFillService remoteService = getService();
if (remoteService != null) {
remoteService.dispatchOnFillRequestSuccess(PendingFillRequest.this,
- request.getFlags(), response);
+ response, request.getFlags());
}
}
@Override
- public void onFailure(CharSequence message) {
+ public void onFailure(int requestId, CharSequence message) {
if (!finish()) return;
final RemoteFillService remoteService = getService();
if (remoteService != null) {
- remoteService.dispatchOnFillRequestFailure(
- PendingFillRequest.this, message);
+ remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this,
+ message);
}
}
};
@@ -566,7 +578,7 @@
if (cancellation != null) {
remoteService.dispatchOnFillTimeout(cancellation);
}
- remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null);
+ remoteService.dispatchOnFillRequestTimeout(PendingFillRequest.this);
}
@Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 73c7172..3bc505a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -27,6 +27,7 @@
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.autofill.Helper.getNumericValue;
import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sPartitionMaxCount;
import static com.android.server.autofill.Helper.sVerbose;
@@ -93,6 +94,7 @@
import com.android.server.autofill.ui.PendingUi;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -176,7 +178,7 @@
/**
* Contexts read from the app; they will be updated (sanitized, change values for save) before
- * sent to {@link AutofillService}. Ordered by the time they we read.
+ * sent to {@link AutofillService}. Ordered by the time they were read.
*/
@GuardedBy("mLock")
private ArrayList<FillContext> mContexts;
@@ -231,6 +233,12 @@
private final LocalLog mWtfHistory;
/**
+ * Map of {@link MetricsEvent#AUTOFILL_REQUEST} metrics, keyed by fill request id.
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
+
+ /**
* Receiver of assist data from the app's {@link Activity}.
*/
private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() {
@@ -483,8 +491,18 @@
requestId = sIdCounter.getAndIncrement();
} while (requestId == INVALID_REQUEST_ID);
+ // Create a metrics log for the request
+ final int ordinal = mRequestLogs.size() + 1;
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_REQUEST_ORDINAL, ordinal);
+ if (flags != 0) {
+ log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags);
+ }
+ mRequestLogs.put(requestId, log);
+
if (sVerbose) {
- Slog.v(TAG, "Requesting structure for requestId=" + requestId + ", flags=" + flags);
+ Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId="
+ + requestId + ", flags=" + flags);
}
// If the focus changes very quickly before the first request is returned each focus change
@@ -537,7 +555,7 @@
setClientLocked(client);
mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
- .addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
}
/**
@@ -604,21 +622,30 @@
// FillServiceCallbacks
@Override
- public void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response,
- @NonNull String servicePackageName) {
+ public void onFillRequestSuccess(int requestId, @Nullable FillResponse response,
+ @NonNull String servicePackageName, int requestFlags) {
final AutofillId[] fieldClassificationIds;
+ final LogMaker requestLog;
+
synchronized (mLock) {
if (mDestroyed) {
Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: "
+ id + " destroyed");
return;
}
+
+ requestLog = mRequestLogs.get(requestId);
+ if (requestLog != null) {
+ requestLog.setType(MetricsEvent.TYPE_SUCCESS);
+ } else {
+ Slog.w(TAG, "onFillRequestSuccess(): no request log for id " + requestId);
+ }
if (response == null) {
+ if (requestLog != null) {
+ requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1);
+ }
processNullResponseLocked(requestFlags);
- mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
- .setType(MetricsEvent.TYPE_SUCCESS)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1));
return;
}
@@ -659,38 +686,54 @@
// Response is "empty" from an UI point of view, need to notify client.
notifyUnavailableToClient(sessionFinishedState);
}
+
+ if (requestLog != null) {
+ requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+ response.getDatasets() == null ? 0 : response.getDatasets().size());
+ if (fieldClassificationIds != null) {
+ requestLog.addTaggedData(
+ MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
+ fieldClassificationIds.length);
+ }
+ }
+
synchronized (mLock) {
processResponseLocked(response, null, requestFlags);
}
-
- final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
- .setType(MetricsEvent.TYPE_SUCCESS)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
- response.getDatasets() == null ? 0 : response.getDatasets().size());
- if (fieldClassificationIds != null) {
- log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
- fieldClassificationIds.length);
- }
- mMetricsLogger.write(log);
}
// FillServiceCallbacks
@Override
- public void onFillRequestFailure(@Nullable CharSequence message,
+ public void onFillRequestFailure(int requestId, @Nullable CharSequence message,
@NonNull String servicePackageName) {
+ onFillRequestFailureOrTimeout(requestId, false, message, servicePackageName);
+ }
+
+ // FillServiceCallbacks
+ @Override
+ public void onFillRequestTimeout(int requestId, @NonNull String servicePackageName) {
+ onFillRequestFailureOrTimeout(requestId, true, null, servicePackageName);
+ }
+
+ private void onFillRequestFailureOrTimeout(int requestId, boolean timedOut,
+ @Nullable CharSequence message, @NonNull String servicePackageName) {
synchronized (mLock) {
if (mDestroyed) {
- Slog.w(TAG, "Call to Session#onFillRequestFailure() rejected - session: "
- + id + " destroyed");
+ Slog.w(TAG, "Call to Session#onFillRequestFailureOrTimeout(req=" + requestId
+ + ") rejected - session: " + id + " destroyed");
return;
}
mService.resetLastResponse();
+ final LogMaker requestLog = mRequestLogs.get(requestId);
+ if (requestLog == null) {
+ Slog.w(TAG, "onFillRequestFailureOrTimeout(): no log for id " + requestId);
+ } else {
+ requestLog.setType(timedOut ? MetricsEvent.TYPE_CLOSE : MetricsEvent.TYPE_FAILURE);
+ }
}
- LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
- .setType(MetricsEvent.TYPE_FAILURE);
- mMetricsLogger.write(log);
-
- getUiForShowing().showError(message, this);
+ if (message != null) {
+ getUiForShowing().showError(message, this);
+ }
removeSelf();
}
@@ -973,11 +1016,12 @@
+ ", clientState=" + newClientState);
}
if (result instanceof FillResponse) {
- writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
+ logAuthenticationStatusLocked(requestId, MetricsEvent.AUTOFILL_AUTHENTICATED);
replaceResponseLocked(authenticatedResponse, (FillResponse) result, newClientState);
} else if (result instanceof Dataset) {
if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
- writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
+ logAuthenticationStatusLocked(requestId,
+ MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
if (newClientState != null) {
if (sDebug) Slog.d(TAG, "Updating client state from auth dataset");
mClientState = newClientState;
@@ -986,13 +1030,15 @@
authenticatedResponse.getDatasets().set(datasetIdx, dataset);
autoFill(requestId, datasetIdx, dataset, false);
} else {
- writeLog(MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
+ logAuthenticationStatusLocked(requestId,
+ MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
}
} else {
if (result != null) {
Slog.w(TAG, "service returned invalid auth type: " + result);
}
- writeLog(MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
+ logAuthenticationStatusLocked(requestId,
+ MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
processNullResponseLocked(0);
}
}
@@ -1253,7 +1299,7 @@
mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
ignoredDatasets, changedFieldIds, changedDatasetIds,
manuallyFilledFieldIds, manuallyFilledDatasetIds,
- mComponentName.getPackageName(), mCompatMode);
+ mComponentName, mCompatMode);
}
}
@@ -1308,7 +1354,7 @@
mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
ignoredDatasets, changedFieldIds, changedDatasetIds,
manuallyFilledFieldIds, manuallyFilledDatasetIds,
- mComponentName.getPackageName(), mCompatMode);
+ mComponentName, mCompatMode);
return;
}
final Scores scores = result.getParcelable(EXTRA_SCORES);
@@ -1373,7 +1419,7 @@
mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications,
- mComponentName.getPackageName(), mCompatMode);
+ mComponentName, mCompatMode);
});
fcStrategy.getScores(callback, algorithm, algorithmArgs, currentValues, userValues);
@@ -1404,7 +1450,7 @@
* the current values of all fields in the screen.
*/
if (saveInfo == null) {
- if (sVerbose) Slog.w(TAG, "showSaveLocked(): no saveInfo from service");
+ if (sVerbose) Slog.v(TAG, "showSaveLocked(): no saveInfo from service");
return true;
}
@@ -1603,7 +1649,7 @@
mPendingSaveUi = new PendingUi(mActivityToken, id, client);
getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
mService.getServicePackageName(), saveInfo, this,
- mComponentName.getPackageName(), this,
+ mComponentName, this,
mPendingSaveUi, mCompatMode);
if (client != null) {
try {
@@ -2065,7 +2111,7 @@
}
@Override
- public void onFillReady(FillResponse response, AutofillId filledId,
+ public void onFillReady(@NonNull FillResponse response, @NonNull AutofillId filledId,
@Nullable AutofillValue value) {
synchronized (mLock) {
if (mDestroyed) {
@@ -2081,7 +2127,7 @@
}
getUiForShowing().showFillUi(filledId, response, filterText,
- mService.getServicePackageName(), mComponentName.getPackageName(),
+ mService.getServicePackageName(), mComponentName,
mService.getServiceLabel(), mService.getServiceIcon(), this, mCompatMode);
synchronized (mLock) {
@@ -2103,9 +2149,8 @@
TimeUtils.formatDuration(duration, historyLog);
mUiLatencyHistory.log(historyLog.toString());
- final LogMaker metricsLog = newLogMaker(MetricsEvent.AUTOFILL_UI_LATENCY)
- .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, duration);
- mMetricsLogger.write(metricsLog);
+ addTaggedDataToRequestLogLocked(response.getRequestId(),
+ MetricsEvent.FIELD_AUTOFILL_DURATION, duration);
}
}
}
@@ -2474,6 +2519,14 @@
TimeUtils.formatDuration(mUiShownTime - mStartTime, pw);
pw.println();
}
+ final int requestLogsSizes = mRequestLogs.size();
+ pw.print(prefix); pw.print("mSessionLogs: "); pw.println(requestLogsSizes);
+ for (int i = 0; i < requestLogsSizes; i++) {
+ final int requestId = mRequestLogs.keyAt(i);
+ final LogMaker log = mRequestLogs.valueAt(i);
+ pw.print(prefix2); pw.print('#'); pw.print(i); pw.print(": req=");
+ pw.print(requestId); pw.print(", log=" ); dumpRequestLog(pw, log); pw.println();
+ }
pw.print(prefix); pw.print("mResponses: ");
if (mResponses == null) {
pw.println("null");
@@ -2532,6 +2585,56 @@
mRemoteFillService.dump(prefix, pw);
}
+ private static void dumpRequestLog(@NonNull PrintWriter pw, @NonNull LogMaker log) {
+ pw.print("CAT="); pw.print(log.getCategory());
+ pw.print(", TYPE=");
+ final int type = log.getType();
+ switch (type) {
+ case MetricsEvent.TYPE_SUCCESS: pw.print("SUCCESS"); break;
+ case MetricsEvent.TYPE_FAILURE: pw.print("FAILURE"); break;
+ case MetricsEvent.TYPE_CLOSE: pw.print("CLOSE"); break;
+ default: pw.print("UNSUPPORTED");
+ }
+ pw.print('('); pw.print(type); pw.print(')');
+ pw.print(", PKG="); pw.print(log.getPackageName());
+ pw.print(", SERVICE="); pw.print(log
+ .getTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE));
+ pw.print(", ORDINAL="); pw.print(log
+ .getTaggedData(MetricsEvent.FIELD_AUTOFILL_REQUEST_ORDINAL));
+ dumpNumericValue(pw, log, "FLAGS", MetricsEvent.FIELD_AUTOFILL_FLAGS);
+ dumpNumericValue(pw, log, "NUM_DATASETS", MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS);
+ dumpNumericValue(pw, log, "UI_LATENCY", MetricsEvent.FIELD_AUTOFILL_DURATION);
+ final int authStatus =
+ getNumericValue(log, MetricsEvent.FIELD_AUTOFILL_AUTHENTICATION_STATUS);
+ if (authStatus != 0) {
+ pw.print(", AUTH_STATUS=");
+ switch (authStatus) {
+ case MetricsEvent.AUTOFILL_AUTHENTICATED:
+ pw.print("AUTHENTICATED"); break;
+ case MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED:
+ pw.print("DATASET_AUTHENTICATED"); break;
+ case MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION:
+ pw.print("INVALID_AUTHENTICATION"); break;
+ case MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION:
+ pw.print("INVALID_DATASET_AUTHENTICATION"); break;
+ default: pw.print("UNSUPPORTED");
+ }
+ pw.print('('); pw.print(authStatus); pw.print(')');
+ }
+ dumpNumericValue(pw, log, "FC_IDS",
+ MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS);
+ dumpNumericValue(pw, log, "COMPAT_MODE",
+ MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE);
+ }
+
+ private static void dumpNumericValue(@NonNull PrintWriter pw, @NonNull LogMaker log,
+ @NonNull String field, int tag) {
+ final int value = getNumericValue(log, tag);
+ if (value != 0) {
+ pw.print(", "); pw.print(field); pw.print('='); pw.print(value);
+ }
+ }
+
void autoFillApp(Dataset dataset) {
synchronized (mLock) {
if (mDestroyed) {
@@ -2610,7 +2713,19 @@
mUi.destroyAll(mPendingSaveUi, this, true);
mUi.clearCallback(this);
mDestroyed = true;
- writeLog(MetricsEvent.AUTOFILL_SESSION_FINISHED);
+
+ // Log metrics
+ final int totalRequests = mRequestLogs.size();
+ if (totalRequests > 0) {
+ if (sVerbose) Slog.v(TAG, "destroyLocked(): logging " + totalRequests + " requests");
+ for (int i = 0; i < totalRequests; i++) {
+ final LogMaker log = mRequestLogs.valueAt(i);
+ mMetricsLogger.write(log);
+ }
+ }
+ mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_FINISHED)
+ .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_REQUESTS, totalRequests));
+
return mRemoteFillService;
}
@@ -2719,14 +2834,36 @@
}
private LogMaker newLogMaker(int category, String servicePackageName) {
- return Helper.newLogMaker(category, mComponentName.getPackageName(), servicePackageName,
- mCompatMode);
+ return Helper.newLogMaker(category, mComponentName, servicePackageName, mCompatMode);
}
private void writeLog(int category) {
mMetricsLogger.write(newLogMaker(category));
}
+ private void logAuthenticationStatusLocked(int requestId, int status) {
+ addTaggedDataToRequestLogLocked(requestId,
+ MetricsEvent.FIELD_AUTOFILL_AUTHENTICATION_STATUS, status);
+ }
+
+ private void addTaggedDataToRequestLogLocked(int requestId, int tag, @Nullable Object value) {
+ final LogMaker requestLog = mRequestLogs.get(requestId);
+ if (requestLog == null) {
+ Slog.w(TAG,
+ "addTaggedDataToRequestLogLocked(tag=" + tag + "): no log for id " + requestId);
+ return;
+ }
+ requestLog.addTaggedData(tag, value);
+ }
+
+ private static String requestLogToString(@NonNull LogMaker log) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ dumpRequestLog(pw, log);
+ pw.flush();
+ return sw.toString();
+ }
+
private void wtf(@Nullable Exception e, String fmt, Object...args) {
final String message = String.format(fmt, args);
mWtfHistory.log(message);
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index cff1a84..bb97e4a 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -19,6 +19,7 @@
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static com.android.server.autofill.Helper.sDebug;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.service.autofill.FillResponse;
@@ -40,7 +41,7 @@
/**
* Called when the fill UI is ready to be shown for this view.
*/
- void onFillReady(FillResponse fillResponse, AutofillId focusedId,
+ void onFillReady(@NonNull FillResponse fillResponse, @NonNull AutofillId focusedId,
@Nullable AutofillValue value);
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 811d87be..f097eff 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
import android.graphics.drawable.Drawable;
@@ -162,21 +163,21 @@
* @param response the current fill response
* @param filterText text of the view to be filled
* @param servicePackageName package name of the autofill service filling the activity
- * @param packageName package name of the activity that is filled
+ * @param componentName component name of the activity that is filled
* @param serviceLabel label of autofill service
* @param serviceIcon icon of autofill service
* @param callback Identifier for the caller
*/
public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
@Nullable String filterText, @Nullable String servicePackageName,
- @NonNull String packageName, @NonNull CharSequence serviceLabel,
+ @NonNull ComponentName componentName, @NonNull CharSequence serviceLabel,
@NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback, boolean compatMode) {
if (sDebug) {
final int size = filterText == null ? 0 : filterText.length();
Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
}
final LogMaker log = Helper
- .newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, packageName, servicePackageName,
+ .newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, componentName, servicePackageName,
compatMode)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
filterText == null ? 0 : filterText.length())
@@ -262,16 +263,18 @@
*/
public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
@Nullable String servicePackageName, @NonNull SaveInfo info,
- @NonNull ValueFinder valueFinder, @NonNull String packageName,
+ @NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
@NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi,
boolean compatMode) {
- if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info);
+ if (sVerbose) {
+ Slog.v(TAG, "showSaveUi() for " + componentName.toShortString() + ": " + info);
+ }
int numIds = 0;
numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
final LogMaker log = Helper
- .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, packageName, servicePackageName,
+ .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, componentName, servicePackageName,
compatMode)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
@@ -281,7 +284,7 @@
}
hideAllUiThread(callback);
mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon,
- servicePackageName, packageName, info, valueFinder, mOverlayControl,
+ servicePackageName, componentName, info, valueFinder, mOverlayControl,
new SaveUi.OnSaveListener() {
@Override
public void onSave() {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index a5311b2..95e85db 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.app.Dialog;
import android.app.PendingIntent;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
@@ -133,14 +134,14 @@
private final CharSequence mSubTitle;
private final PendingUi mPendingUi;
private final String mServicePackageName;
- private final String mPackageName;
+ private final ComponentName mComponentName;
private final boolean mCompatMode;
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
- @Nullable String servicePackageName, @NonNull String packageName,
+ @Nullable String servicePackageName, @NonNull ComponentName componentName,
@NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
boolean compatMode) {
@@ -148,7 +149,7 @@
mListener = new OneTimeListener(listener);
mOverlayControl = overlayControl;
mServicePackageName = servicePackageName;
- mPackageName = packageName;
+ mComponentName = componentName;
mCompatMode = compatMode;
context = new ContextThemeWrapper(context, THEME_ID);
@@ -412,12 +413,12 @@
}
private LogMaker newLogMaker(int category, int saveType) {
- return Helper.newLogMaker(category, mPackageName, mServicePackageName, mCompatMode)
+ return Helper.newLogMaker(category, mComponentName, mServicePackageName, mCompatMode)
.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType);
}
private LogMaker newLogMaker(int category) {
- return Helper.newLogMaker(category, mPackageName, mServicePackageName, mCompatMode);
+ return Helper.newLogMaker(category, mComponentName, mServicePackageName, mCompatMode);
}
private void writeLog(int category, int saveType) {
@@ -505,7 +506,7 @@
pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi);
pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName);
- pw.print(prefix); pw.print("app: "); pw.println(mPackageName);
+ pw.print(prefix); pw.print("app: "); pw.println(mComponentName.toShortString());
pw.print(prefix); pw.print("compat mode: "); pw.println(mCompatMode);
final View view = mDialog.getWindow().getDecorView();
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/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 d5f936b..e810b1a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13943,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);
@@ -14007,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);
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/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;
}