Merge "Add unit tests to libprotoutil."
diff --git a/Android.bp b/Android.bp
index add6117..e120efd 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1039,6 +1039,7 @@
],
api_filename: "public_api.txt",
removed_api_filename: "removed.txt",
+ removed_dex_api_filename: "removed-dex.txt",
args: framework_docs_args + " -referenceonly -nodocs",
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 73b72fa..50aaa0a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -965,13 +965,6 @@
method public void setCarrierTestOverride(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
}
-
- public class TelephonyManager {
- method public int getCarrierIdListVersion();
- method public void setCarrierTestOverride(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
- field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
- }
-
}
package android.telephony.mbms {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 71f126f..a1219ea 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -229,6 +229,7 @@
Landroid/app/AppOpsManager;->OP_WRITE_CONTACTS:I
Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
Landroid/app/AppOpsManager;->permissionToOpCode(Ljava/lang/String;)I
+Landroid/app/AppOpsManager;->setRestriction(III[Ljava/lang/String;)V
Landroid/app/AppOpsManager;->sOpPerms:[Ljava/lang/String;
Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
Landroid/app/backup/BackupDataInput$EntityHeader;->dataSize:I
@@ -420,6 +421,7 @@
Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent;
Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent;
Landroid/app/PendingIntent;->isActivity()Z
+Landroid/app/PictureInPictureParams;->getAspectRatio()F
Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView;
Landroid/app/QueuedWork;->addFinisher(Ljava/lang/Runnable;)V
@@ -695,6 +697,7 @@
Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
+Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
@@ -738,6 +741,7 @@
Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
+Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
@@ -796,6 +800,7 @@
Landroid/content/pm/PackageParser$Package;->configPreferences:Ljava/util/ArrayList;
Landroid/content/pm/PackageParser$Package;->instrumentation:Ljava/util/ArrayList;
Landroid/content/pm/PackageParser$Package;->mAppMetaData:Landroid/os/Bundle;
+Landroid/content/pm/PackageParser$Package;->mKeySetMapping:Landroid/util/ArrayMap;
Landroid/content/pm/PackageParser$Package;->mPreferredOrder:I
Landroid/content/pm/PackageParser$Package;->mSharedUserId:Ljava/lang/String;
Landroid/content/pm/PackageParser$Package;->mSharedUserLabel:I
@@ -891,6 +896,7 @@
Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
+Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
Landroid/content/res/ResourcesImpl;->mAnimatorCache:Landroid/content/res/ConfigurationBoundResourceCache;
Landroid/content/res/ResourcesImpl;->mAssets:Landroid/content/res/AssetManager;
@@ -1262,6 +1268,7 @@
Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
+Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;)Landroid/icu/text/Transliterator;
Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
@@ -2093,6 +2100,7 @@
Landroid/R$styleable;->CheckedTextView_checkMark:I
Landroid/R$styleable;->CompoundButton:[I
Landroid/R$styleable;->CompoundButton_button:I
+Landroid/R$styleable;->DrawableStates:[I
Landroid/R$styleable;->ImageView:[I
Landroid/R$styleable;->ImageView_adjustViewBounds:I
Landroid/R$styleable;->ImageView_baselineAlignBottom:I
@@ -2355,6 +2363,7 @@
Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
Landroid/telephony/CellSignalStrengthLte;->mRssnr:I
Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
+Landroid/telephony/CellSignalStrengthLte;->mTimingAdvance:I
Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
@@ -2364,6 +2373,7 @@
Landroid/telephony/SignalStrength;->getAsuLevel()I
Landroid/telephony/SignalStrength;->getCdmaLevel()I
Landroid/telephony/SignalStrength;->getDbm()I
+Landroid/telephony/SignalStrength;->getGsmDbm()I
Landroid/telephony/SignalStrength;->getLteDbm()I
Landroid/telephony/SignalStrength;->getLteRsrp()I
Landroid/telephony/SignalStrength;->getLteRsrq()I
@@ -2428,6 +2438,7 @@
Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
+Landroid/telephony/TelephonyManager;->isVideoTelephonyAvailable()Z
Landroid/telephony/TelephonyManager;->isVolteAvailable()Z
Landroid/telephony/TelephonyManager;->isWifiCallingAvailable()Z
Landroid/telephony/TelephonyManager;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
@@ -2606,6 +2617,7 @@
Landroid/view/inputmethod/InputMethodManager;->finishInputLocked()V
Landroid/view/inputmethod/InputMethodManager;->focusIn(Landroid/view/View;)V
Landroid/view/inputmethod/InputMethodManager;->focusOut(Landroid/view/View;)V
+Landroid/view/inputmethod/InputMethodManager;->getClient()Lcom/android/internal/view/IInputMethodClient;
Landroid/view/inputmethod/InputMethodManager;->getInputMethodWindowVisibleHeight()I
Landroid/view/inputmethod/InputMethodManager;->getInstance()Landroid/view/inputmethod/InputMethodManager;
Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String;
@@ -2782,6 +2794,7 @@
Landroid/view/View;->includeForAccessibility()Z
Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
Landroid/view/View;->internalSetPadding(IIII)V
+Landroid/view/View;->invalidateParentIfNeeded()V
Landroid/view/View;->isPaddingResolved()Z
Landroid/view/View;->isRootNamespace()Z
Landroid/view/View;->isVisibleToUser()Z
@@ -3066,6 +3079,7 @@
Landroid/widget/ImageView;->mDrawMatrix:Landroid/graphics/Matrix;
Landroid/widget/ImageView;->mMaxHeight:I
Landroid/widget/ImageView;->mMaxWidth:I
+Landroid/widget/ImageView;->mRecycleableBitmapDrawable:Landroid/graphics/drawable/BitmapDrawable;
Landroid/widget/ImageView;->mResource:I
Landroid/widget/ImageView;->mUri:Landroid/net/Uri;
Landroid/widget/ImageView;->updateDrawable(Landroid/graphics/drawable/Drawable;)V
@@ -3570,11 +3584,13 @@
Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
Lcom/android/internal/telephony/ITelephony;->endCall()Z
+Lcom/android/internal/telephony/ITelephony;->endCallForSubscriber(I)Z
Lcom/android/internal/telephony/ITelephony;->getCallState()I
Lcom/android/internal/telephony/ITelephony;->getDataState()I
Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
+Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
Lcom/android/internal/telephony/SmsHeader$ConcatRef;->msgCount:I
@@ -3711,6 +3727,7 @@
Ldalvik/system/VMDebug;->isDebuggerConnected()Z
Ldalvik/system/VMRuntime;->addressOf(Ljava/lang/Object;)J
Ldalvik/system/VMRuntime;->clearGrowthLimit()V
+Ldalvik/system/VMRuntime;->gcSoftReferences()V
Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
Ldalvik/system/VMRuntime;->getExternalBytesAllocated()J
Ldalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index a44bd03..07b4b9c 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -16,8 +16,6 @@
package android.app;
-import com.android.internal.app.AlertController;
-
import android.annotation.ArrayRes;
import android.annotation.AttrRes;
import android.annotation.DrawableRes;
@@ -30,17 +28,19 @@
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Message;
+import android.text.Layout;
+import android.text.method.MovementMethod;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
import android.view.View;
-import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.android.internal.R;
+import com.android.internal.app.AlertController;
/**
* A subclass of Dialog that can display one, two or three buttons. If you only want to
@@ -54,7 +54,7 @@
* </pre>
*
* <p>The AlertDialog class takes care of automatically setting
- * {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
+ * {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
* WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether
* any views in the dialog return true from {@link View#onCheckIsTextEditor()
* View.onCheckIsTextEditor()}. Generally you want this set for a Dialog
@@ -266,6 +266,17 @@
mAlert.setMessage(message);
}
+ /** @hide */
+ public void setMessageMovementMethod(MovementMethod movementMethod) {
+ mAlert.setMessageMovementMethod(movementMethod);
+ }
+
+ /** @hide */
+ public void setMessageHyphenationFrequency(
+ @Layout.HyphenationFrequency int hyphenationFrequency) {
+ mAlert.setMessageHyphenationFrequency(hyphenationFrequency);
+ }
+
/**
* Set the view to display in that dialog.
*/
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 30451c2..583f060 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -93,6 +93,8 @@
public static final long TRACE_TAG_VIBRATOR = 1L << 23;
/** @hide */
public static final long TRACE_TAG_AIDL = 1L << 24;
+ /** @hide */
+ public static final long TRACE_TAG_NNAPI = 1L << 25;
private static final long TRACE_TAG_NOT_READY = 1L << 63;
private static final int MAX_SECTION_NAME_LEN = 127;
diff --git a/core/java/android/printservice/recommendation/RecommendationService.java b/core/java/android/printservice/recommendation/RecommendationService.java
index 733629a..968a625 100644
--- a/core/java/android/printservice/recommendation/RecommendationService.java
+++ b/core/java/android/printservice/recommendation/RecommendationService.java
@@ -119,14 +119,16 @@
mCallbacks = null;
break;
case MSG_UPDATE:
- // Note that there might be a connection change in progress. In this case the
- // message is handled as before the change. This is acceptable as the caller of
- // the connection change has not guarantee when the connection change binder
- // transaction is actually processed.
- try {
- mCallbacks.onRecommendationsUpdated((List<RecommendationInfo>) msg.obj);
- } catch (RemoteException | NullPointerException e) {
- Log.e(LOG_TAG, "Could not update recommended services", e);
+ if (mCallbacks != null) {
+ // Note that there might be a connection change in progress. In this case
+ // the message is handled as before the change. This is acceptable as the
+ // caller of the connection change has not guarantee when the connection
+ // change binder transaction is actually processed.
+ try {
+ mCallbacks.onRecommendationsUpdated((List<RecommendationInfo>) msg.obj);
+ } catch (RemoteException | NullPointerException e) {
+ Log.e(LOG_TAG, "Could not update recommended services", e);
+ }
}
break;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9751b7f..da45269 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10804,16 +10804,29 @@
public static final String SYNC_MANAGER_CONSTANTS = "sync_manager_constants";
/**
- * Whether or not App Standby feature is enabled. This controls throttling of apps
- * based on usage patterns and predictions.
+ * Whether or not App Standby feature is enabled by system. This controls throttling of apps
+ * based on usage patterns and predictions. Platform will turn on this feature if both this
+ * flag and {@link #ADAPTIVE_BATTERY_MANAGEMENT_ENABLED} is on.
* Type: int (0 for false, 1 for true)
* Default: 1
* @hide
+ * @see #ADAPTIVE_BATTERY_MANAGEMENT_ENABLED
*/
@SystemApi
public static final String APP_STANDBY_ENABLED = "app_standby_enabled";
/**
+ * Whether or not adaptive battery feature is enabled by user. Platform will turn on this
+ * feature if both this flag and {@link #APP_STANDBY_ENABLED} is on.
+ * Type: int (0 for false, 1 for true)
+ * Default: 1
+ * @hide
+ * @see #APP_STANDBY_ENABLED
+ */
+ public static final String ADAPTIVE_BATTERY_MANAGEMENT_ENABLED =
+ "adaptive_battery_management_enabled";
+
+ /**
* Whether or not app auto restriction is enabled. When it is enabled, settings app will
* auto restrict the app if it has bad behavior(e.g. hold wakelock for long time).
*
diff --git a/core/java/android/service/autofill/BatchUpdates.java b/core/java/android/service/autofill/BatchUpdates.java
index 90acc88..2ba0376 100644
--- a/core/java/android/service/autofill/BatchUpdates.java
+++ b/core/java/android/service/autofill/BatchUpdates.java
@@ -82,6 +82,9 @@
* {@link #transformChild(int, Transformation) transformations} are applied to the children
* views.
*
+ * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+ * or background color: Autofill on different platforms may have different themes.
+ *
* @param updates a {@link RemoteViews} with the updated actions to be applied in the
* underlying presentation template.
*
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index ccec483..5211767 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -336,6 +336,9 @@
* higher, datasets that require authentication can be also be filtered by passing a
* {@link AutofillValue#forText(CharSequence) text value} as the {@code value} parameter.
*
+ * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+ * or background color: Autofill on different platforms may have different themes.
+ *
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
* @param value the value to be autofilled. Pass {@code null} if you do not have the value
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 2bc4b8f..7bf1f83 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -241,6 +241,9 @@
* immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
* platform needs to fill in the authentication arguments.
*
+ * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+ * or background color: Autofill on different platforms may have different themes.
+ *
* @param authentication Intent to an activity with your authentication flow.
* @param presentation The presentation to visualize the response.
* @param ids id of Views that when focused will display the authentication UI.
@@ -449,6 +452,9 @@
* authentication (as the header could have been set directly in the main presentation in
* these cases).
*
+ * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+ * or background color: Autofill on different platforms may have different themes.
+ *
* @param header a presentation to represent the header. This presentation is not clickable
* —calling
* {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
@@ -477,6 +483,9 @@
* authentication (as the footer could have been set directly in the main presentation in
* these cases).
*
+ * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+ * or background color: Autofill on different platforms may have different themes.
+ *
* @param footer a presentation to represent the footer. This presentation is not clickable
* —calling
* {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index a6495d1..8266207 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -19,6 +19,7 @@
import static android.view.autofill.Helper.sVerbose;
import android.annotation.NonNull;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
@@ -79,11 +80,6 @@
public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
mWindowPresenter = new WindowPresenter(presenter);
- // We want to show the window as system controlled one so it covers app windows, but it has
- // to be an application type (so it's contained inside the application area).
- // Hence, we set it to the application type with the highest z-order, which currently
- // is TYPE_APPLICATION_ABOVE_SUB_PANEL.
- setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
setTouchModal(false);
setOutsideTouchable(true);
setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
@@ -110,7 +106,16 @@
*/
public void update(View anchor, int offsetX, int offsetY, int width, int height,
Rect virtualBounds) {
- mFullScreen = width == LayoutParams.MATCH_PARENT && height == LayoutParams.MATCH_PARENT;
+ mFullScreen = width == LayoutParams.MATCH_PARENT;
+ // For no fullscreen autofill window, we want to show the window as system controlled one
+ // so it covers app windows, but it has to be an application type (so it's contained inside
+ // the application area). Hence, we set it to the application type with the highest z-order,
+ // which currently is TYPE_APPLICATION_ABOVE_SUB_PANEL.
+ // For fullscreen mode, autofill window is at the bottom of screen, it should not be
+ // clipped by app activity window. Fullscreen autofill window does not need to follow app
+ // anchor view position.
+ setWindowLayoutType(mFullScreen ? WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
+ : WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
// If we are showing the popup for a virtual view we use a fake view which
// delegates to the anchor but present itself with the same bounds as the
// virtual view. This ensures that the location logic in popup works
@@ -119,6 +124,15 @@
if (mFullScreen) {
offsetX = 0;
offsetY = 0;
+ // If it is not fullscreen height, put window at bottom. Computes absolute position.
+ // Note that we cannot easily change default gravity from Gravity.TOP to
+ // Gravity.BOTTOM because PopupWindow base class does not expose computeGravity().
+ final Point outPoint = new Point();
+ anchor.getContext().getDisplay().getSize(outPoint);
+ width = outPoint.x;
+ if (height != LayoutParams.MATCH_PARENT) {
+ offsetY = outPoint.y - height;
+ }
actualAnchor = anchor;
} else if (virtualBounds != null) {
final int[] mLocationOnScreen = new int[] {virtualBounds.left, virtualBounds.top};
@@ -202,6 +216,16 @@
actualAnchor = anchor;
}
+ if (!mFullScreen) {
+ // No fullscreen window animation is controlled by PopupWindow.
+ setAnimationStyle(-1);
+ } else if (height == LayoutParams.MATCH_PARENT) {
+ // Complete fullscreen autofill window has no animation.
+ setAnimationStyle(0);
+ } else {
+ // Slide half screen height autofill window from bottom.
+ setAnimationStyle(com.android.internal.R.style.AutofillHalfScreenAnimation);
+ }
if (!isShowing()) {
setWidth(width);
setHeight(height);
@@ -223,7 +247,12 @@
protected boolean findDropDownPosition(View anchor, LayoutParams outParams,
int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
if (mFullScreen) {
- // Do not patch LayoutParams if force full screen
+ // In fullscreen mode, don't need consider the anchor view.
+ outParams.x = xOffset;
+ outParams.y = yOffset;
+ outParams.width = width;
+ outParams.height = height;
+ outParams.gravity = gravity;
return false;
}
return super.findDropDownPosition(anchor, outParams, xOffset, yOffset,
@@ -316,11 +345,6 @@
}
@Override
- public void setAnimationStyle(int animationStyle) {
- throw new IllegalStateException("You can't call this!");
- }
-
- @Override
public void setBackgroundDrawable(Drawable background) {
throw new IllegalStateException("You can't call this!");
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index cb362e6..f1a1457 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -170,7 +170,7 @@
if (mWindow == null) {
synchronized (mLock) {
mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
- getValidViewSurface(),
+ getValidParentSurfaceForMagnifier(),
mWindowWidth, mWindowHeight, mWindowElevation, mWindowCornerRadius,
Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
mCallback);
@@ -245,18 +245,20 @@
}
@Nullable
- private Surface getValidViewSurface() {
- // TODO: deduplicate this against the first part of #performPixelCopy
- final Surface surface;
- if (mView instanceof SurfaceView) {
- surface = ((SurfaceView) mView).getHolder().getSurface();
- } else if (mView.getViewRootImpl() != null) {
- surface = mView.getViewRootImpl().mSurface;
- } else {
- surface = null;
+ private Surface getValidParentSurfaceForMagnifier() {
+ if (mView.getViewRootImpl() != null) {
+ final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
+ if (mainWindowSurface != null && mainWindowSurface.isValid()) {
+ return mainWindowSurface;
+ }
}
-
- return (surface != null && surface.isValid()) ? surface : null;
+ if (mView instanceof SurfaceView) {
+ final Surface surfaceViewSurface = ((SurfaceView) mView).getHolder().getSurface();
+ if (surfaceViewSurface != null && surfaceViewSurface.isValid()) {
+ return surfaceViewSurface;
+ }
+ }
+ return null;
}
private void configureCoordinates(final float xPosInView, final float yPosInView) {
@@ -264,12 +266,12 @@
// magnifier. These are relative to the surface the content is copied from.
final float posX;
final float posY;
+ mView.getLocationInSurface(mViewCoordinatesInSurface);
if (mView instanceof SurfaceView) {
// No offset required if the backing Surface matches the size of the SurfaceView.
posX = xPosInView;
posY = yPosInView;
} else {
- mView.getLocationInSurface(mViewCoordinatesInSurface);
posX = xPosInView + mViewCoordinatesInSurface[0];
posY = yPosInView + mViewCoordinatesInSurface[1];
}
@@ -282,6 +284,14 @@
R.dimen.magnifier_offset);
mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalOffset;
+ if (mView instanceof SurfaceView && mView.getViewRootImpl() != null) {
+ // TODO: deduplicate against the first part of #getValidParentSurfaceForMagnifier()
+ final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
+ if (mainWindowSurface != null && mainWindowSurface.isValid()) {
+ mWindowCoords.x += mViewCoordinatesInSurface[0];
+ mWindowCoords.y += mViewCoordinatesInSurface[1];
+ }
+ }
}
private void performPixelCopy(final int startXInSurface, final int startYInSurface,
@@ -361,6 +371,9 @@
// The alpha set on the magnifier's content, which defines how
// prominent the white background is.
private static final int CONTENT_BITMAP_ALPHA = 242;
+ // The z of the magnifier surface, defining its z order in the list of
+ // siblings having the same parent surface (usually the main app surface).
+ private static final int SURFACE_Z = 5;
// Display associated to the view the magnifier is attached to.
private final Display mDisplay;
@@ -602,6 +615,7 @@
mSurfaceControl.setPosition(pendingX, pendingY);
}
if (firstDraw) {
+ mSurfaceControl.setLayer(SURFACE_Z);
mSurfaceControl.show();
}
SurfaceControl.closeTransaction();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5ecbf90a..4865dab 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -21,6 +21,7 @@
import android.annotation.ColorInt;
import android.annotation.DimenRes;
import android.annotation.NonNull;
+import android.annotation.StyleRes;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
@@ -56,6 +57,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Filter;
import android.view.RemotableViewMethod;
@@ -182,6 +184,12 @@
private boolean mIsRoot = true;
/**
+ * Optional theme resource id applied in inflateView(). When 0, Theme.DeviceDefault will be
+ * used.
+ */
+ private int mApplyThemeResId;
+
+ /**
* Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
* the layout in a way that isn't recoverable, since views are being removed.
*/
@@ -3267,6 +3275,14 @@
}
/**
+ * Set the theme used in apply() and applyASync().
+ * @hide
+ */
+ public void setApplyTheme(@StyleRes int themeResId) {
+ mApplyThemeResId = themeResId;
+ }
+
+ /**
* Inflates the view hierarchy represented by this object and applies
* all of the actions.
*
@@ -3301,6 +3317,10 @@
final Context contextForResources = getContextForResources(context);
Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
+ // If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
+ if (mApplyThemeResId != 0) {
+ inflationContext = new ContextThemeWrapper(inflationContext, mApplyThemeResId);
+ }
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 46cb546..7321721 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -30,7 +30,10 @@
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
+import android.text.Layout;
import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.method.MovementMethod;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
@@ -101,6 +104,9 @@
private ImageView mIconView;
private TextView mTitleView;
protected TextView mMessageView;
+ private MovementMethod mMessageMovementMethod;
+ @Layout.HyphenationFrequency
+ private Integer mMessageHyphenationFrequency;
private View mCustomTitleView;
private boolean mForceInverseBackground;
@@ -290,6 +296,21 @@
}
}
+ public void setMessageMovementMethod(MovementMethod movementMethod) {
+ mMessageMovementMethod = movementMethod;
+ if (mMessageView != null) {
+ mMessageView.setMovementMethod(movementMethod);
+ }
+ }
+
+ public void setMessageHyphenationFrequency(
+ @Layout.HyphenationFrequency int hyphenationFrequency) {
+ mMessageHyphenationFrequency = hyphenationFrequency;
+ if (mMessageView != null) {
+ mMessageView.setHyphenationFrequency(hyphenationFrequency);
+ }
+ }
+
/**
* Set the view resource to display in the dialog.
*/
@@ -676,6 +697,12 @@
if (mMessage != null) {
mMessageView.setText(mMessage);
+ if (mMessageMovementMethod != null) {
+ mMessageView.setMovementMethod(mMessageMovementMethod);
+ }
+ if (mMessageHyphenationFrequency != null) {
+ mMessageView.setHyphenationFrequency(mMessageHyphenationFrequency);
+ }
} else {
mMessageView.setVisibility(View.GONE);
mScrollView.removeView(mMessageView);
diff --git a/core/res/res/layout-television/autofill_save.xml b/core/res/res/layout-television/autofill_save.xml
new file mode 100644
index 0000000..ebd2dec
--- /dev/null
+++ b/core/res/res/layout-television/autofill_save.xml
@@ -0,0 +1,100 @@
+<?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.
+-->
+
+<!-- NOTE: outer layout is required to provide proper shadow. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:id="@+id/autofill_save"
+ android:background="?android:attr/colorBackground"
+ android:layout_marginTop="32dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="40dp"
+ android:paddingEnd="40dp"
+ android:paddingTop="40dp"
+ android:paddingBottom="40dp">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginEnd="32dp">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="6dp">
+
+ <ImageView
+ android:id="@+id/autofill_save_icon"
+ android:scaleType="fitStart"
+ android:layout_marginEnd="10dp"
+ android:layout_gravity="center_vertical"
+ android:layout_width="48dp"
+ android:layout_height="48dp"/>
+ <TextView
+ android:id="@+id/autofill_save_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/autofill_save_title"
+ android:layout_gravity="center_vertical"
+ android:textSize="24sp" />
+ </LinearLayout>
+
+ <com.android.server.autofill.ui.CustomScrollView
+ android:id="@+id/autofill_save_custom_subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dp"
+ android:visibility="gone"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="304dp"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/autofill_save_no"
+ style="?attr/borderlessButtonStyle"
+ android:textAlignment="viewStart"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/autofill_save_no">
+ </Button>
+
+ <Button
+ android:id="@+id/autofill_save_yes"
+ style="?attr/borderlessButtonStyle"
+ android:textAlignment="viewStart"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/autofill_save_yes">
+ </Button>
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index ef19f87..a88836e 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
-<view xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/autofill_dataset_picker"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
@@ -31,4 +30,4 @@
android:visibility="gone">
</ListView>
-</view>
+</FrameLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
index 07298c1..1d2b5e5 100644
--- a/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
+++ b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
@@ -14,35 +14,73 @@
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/autofill_dataset_picker"
- style="@style/AutofillDatasetPicker"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:background="?android:attr/windowBackground"
+ android:paddingStart="40dp"
+ android:paddingEnd="40dp"
+ android:paddingTop="40dp"
+ android:paddingBottom="40dp">
- <TextView
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:text="@string/autofill_window_title"
- android:layout_above="@+id/autofill_dataset_container"
- android:layout_alignStart="@+id/autofill_dataset_container"
- android:textSize="16sp"/>
+ android:layout_weight="1"
+ android:layout_marginEnd="32dp">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="6dp"
+ >
+ <ImageView
+ android:id="@+id/autofill_dataset_icon"
+ android:scaleType="fitStart"
+ android:layout_marginEnd="10dp"
+ android:layout_gravity="center_vertical"
+ android:layout_width="48dp"
+ android:layout_height="48dp"/>
+ <TextView
+ android:id="@+id/autofill_dataset_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:textSize="24sp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/autofill_dataset_header"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+
+ </LinearLayout>
<!-- autofill_container is the common parent for inserting authentication item or
- autofill_dataset_list-->
- <FrameLayout
- android:id="@+id/autofill_dataset_container"
- android:layout_width="wrap_content"
+ autofill_dataset_list, autofill_dataset_foolter-->
+ <LinearLayout
+ android:layout_width="304dp"
android:layout_height="wrap_content"
- android:layout_centerInParent="true">
+ android:id="@+id/autofill_dataset_picker"
+ android:orientation="vertical">
<ListView
android:id="@+id/autofill_dataset_list"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:divider="@null"
android:drawSelectorOnTop="true"
android:visibility="gone"/>
- </FrameLayout>
+ <LinearLayout
+ android:id="@+id/autofill_dataset_footer"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"/>
+ </LinearLayout>
-</RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer.xml b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
index 048494a..093f035 100644
--- a/core/res/res/layout/autofill_dataset_picker_header_footer.xml
+++ b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
@@ -14,8 +14,7 @@
limitations under the License.
-->
-<view xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/autofill_dataset_picker"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
@@ -54,4 +53,4 @@
</LinearLayout>
-</view>
+</FrameLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
deleted file mode 100644
index 24b14a0..0000000
--- a/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/autofill_dataset_picker"
- style="@style/AutofillDatasetPicker"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/autofill_window_title"
- android:layout_above="@+id/autofill_dataset_container"
- android:layout_alignStart="@+id/autofill_dataset_container"
- android:textSize="16sp"/>
-
- <!-- autofill_container is the common parent for inserting authentication item or
- autofill_dataset_list-->
- <FrameLayout
- android:id="@+id/autofill_dataset_container"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true">
-
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/autofill_dataset_header"
- android:visibility="gone"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"/>
-
- <ListView
- android:id="@+id/autofill_dataset_list"
- android:layout_weight="1"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:clickable="true"
- android:divider="@null"
- android:drawSelectorOnTop="true"
- android:visibility="gone"/>
-
- <LinearLayout
- android:id="@+id/autofill_dataset_footer"
- android:visibility="gone"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"/>
-
- </LinearLayout>
-
- </FrameLayout>
-
-</RelativeLayout>
diff --git a/core/res/res/values-television/dimens.xml b/core/res/res/values-television/dimens.xml
index aa56251..4c25225 100644
--- a/core/res/res/values-television/dimens.xml
+++ b/core/res/res/values-television/dimens.xml
@@ -20,8 +20,4 @@
<item type="dimen" format="float" name="ambient_shadow_alpha">0.15</item>
<item type="dimen" format="float" name="spot_shadow_alpha">0.3</item>
- <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
- <dimen name="autofill_dataset_picker_max_width">60%</dimen>
- <dimen name="autofill_dataset_picker_max_height">70%</dimen>
-
</resources>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index e01caa3..e380a7b 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -16,4 +16,6 @@
<resources>
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
<style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+ <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill" />
+ <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save" />
</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 3609fb8..2966aff 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -145,4 +145,8 @@
<color name="datepicker_default_view_animator_color_material_light">#fff2f2f2</color>
<color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
+ <!-- Autofill colors -->
+ <color name="autofill_background_material_dark">@color/material_blue_grey_900</color>
+ <color name="autofill_background_material_light">@color/material_grey_50</color>
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 395b269..b92052b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2196,8 +2196,8 @@
<!-- Text to show in the auto complete drop down list on a text view when the WebView can auto fill the entire form but the user has not configured an AutoFill profile [CHAR-LIMIT=19] -->
<string name="setup_autofill">Set up Autofill</string>
- <!-- Title of fullscreen autofill window [CHAR-LIMIT=80] -->
- <string name="autofill_window_title">Autofill</string>
+ <!-- Title of fullscreen autofill window, including the name of which autofill service it is using [CHAR-LIMIT=NONE] -->
+ <string name="autofill_window_title">Autofill with <xliff:g id="serviceName" example="MyPass">%1$s</xliff:g></string>
<!-- String used to separate FirstName and LastName when writing out a local name
e.g. John<separator>Smith [CHAR-LIMIT=NONE]-->
@@ -4514,7 +4514,10 @@
<!-- Notification shown when device owner silently deletes a package [CHAR LIMIT=NONE] -->
<string name="package_deleted_device_owner">Deleted by your admin</string>
- <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
+ <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, with a "learn more" link. -->
+ <string name="battery_saver_description_with_learn_more">To extend your battery life, Battery Saver turns off some device features and restricts apps. <annotation id="url">Learn More</annotation></string>
+
+ <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, without a "learn more" link. -->
<string name="battery_saver_description">To extend your battery life, Battery Saver turns off some device features and restricts apps.</string>
<!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 984461b..50a6ff3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1487,13 +1487,19 @@
<item name="successColor">@color/lock_pattern_view_success_color</item>
</style>
- <!-- @hide -->
+ <!-- @hide Autofill background for popup window (not for fullscreen) -->
<style name="AutofillDatasetPicker">
<item name="elevation">4dp</item>
<item name="background">@drawable/autofill_dataset_picker_background</item>
</style>
<!-- @hide -->
+ <style name="AutofillHalfScreenAnimation">
+ <item name="android:windowEnterAnimation">@anim/slide_in_up</item>
+ <item name="android:windowExitAnimation">@anim/slide_out_down</item>
+ </style>
+
+ <!-- @hide -->
<style name="AutofillSaveAnimation">
<item name="android:windowEnterAnimation">@anim/slide_in_up</item>
<item name="android:windowExitAnimation">@anim/slide_out_down</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7cc88e8..d7a1ecc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -663,6 +663,7 @@
<java-symbol type="string" name="autofill_state_re" />
<java-symbol type="string" name="autofill_this_form" />
<java-symbol type="string" name="autofill_username_re" />
+ <java-symbol type="string" name="autofill_window_title" />
<java-symbol type="string" name="autofill_zip_4_re" />
<java-symbol type="string" name="autofill_zip_code" />
<java-symbol type="string" name="autofill_zip_code_re" />
@@ -3055,13 +3056,13 @@
<java-symbol type="layout" name="autofill_dataset_picker"/>
<java-symbol type="layout" name="autofill_dataset_picker_fullscreen"/>
<java-symbol type="layout" name="autofill_dataset_picker_header_footer"/>
- <java-symbol type="layout" name="autofill_dataset_picker_header_footer_fullscreen"/>
<java-symbol type="id" name="autofill" />
- <java-symbol type="id" name="autofill_dataset_container"/>
<java-symbol type="id" name="autofill_dataset_footer"/>
<java-symbol type="id" name="autofill_dataset_header"/>
+ <java-symbol type="id" name="autofill_dataset_icon" />
<java-symbol type="id" name="autofill_dataset_list"/>
<java-symbol type="id" name="autofill_dataset_picker"/>
+ <java-symbol type="id" name="autofill_dataset_title" />
<java-symbol type="id" name="autofill_save_custom_subtitle" />
<java-symbol type="id" name="autofill_save_icon" />
<java-symbol type="id" name="autofill_save_no" />
@@ -3086,6 +3087,7 @@
<java-symbol type="string" name="autofill_save_type_email_address" />
<java-symbol type="drawable" name="autofill_dataset_picker_background" />
<java-symbol type="style" name="AutofillDatasetPicker" />
+ <java-symbol type="style" name="AutofillHalfScreenAnimation" />
<java-symbol type="style" name="AutofillSaveAnimation" />
<java-symbol type="dimen" name="autofill_dataset_picker_max_width"/>
<java-symbol type="dimen" name="autofill_dataset_picker_max_height"/>
@@ -3093,6 +3095,9 @@
<java-symbol type="dimen" name="autofill_save_icon_max_size"/>
<java-symbol type="integer" name="autofill_max_visible_datasets" />
+ <java-symbol type="style" name="Theme.DeviceDefault.Autofill" />
+ <java-symbol type="style" name="Theme.DeviceDefault.Autofill.Save" />
+
<java-symbol type="dimen" name="notification_big_picture_max_height"/>
<java-symbol type="dimen" name="notification_big_picture_max_width"/>
<java-symbol type="dimen" name="notification_media_image_max_width"/>
@@ -3373,4 +3378,5 @@
<java-symbol type="id" name="user_loading_avatar" />
<java-symbol type="id" name="user_loading" />
+ <java-symbol type="string" name="battery_saver_description_with_learn_more" />
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 92b2f33..14e5082 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1673,6 +1673,15 @@
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
</style>
+
+ <!-- @hide DeviceDefault theme for the autofill FillUi -->
+ <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill.Light">
+ </style>
+
+ <!-- @hide DeviceDefault theme for the autofill SaveUi -->
+ <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save.Light">
+ </style>
+
<!-- DeviceDefault theme for the default system theme. -->
<style name="Theme.DeviceDefault.System" parent="Theme.DeviceDefault.Light.DarkActionBar" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 9b633fc..b3e33d5 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1417,4 +1417,25 @@
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
<item name="colorSecondary">@color/secondary_material_settings</item>
</style>
+
+ <!-- @hide -->
+ <style name="Theme.Material.Autofill" parent="Theme.Material">
+ <item name="colorBackground">@color/autofill_background_material_dark</item>
+ </style>
+
+ <!-- @hide -->
+ <style name="Theme.Material.Autofill.Light" parent="Theme.Material.Light">
+ <item name="colorBackground">@color/autofill_background_material_light</item>
+ </style>
+
+ <!-- @hide -->
+ <style name="Theme.Material.Autofill.Save" parent="Theme.Material.Panel">
+ <item name="colorBackground">@color/autofill_background_material_dark</item>
+ </style>
+
+ <!-- @hide -->
+ <style name="Theme.Material.Autofill.Save.Light" parent="Theme.Material.Light.Panel">
+ <item name="colorBackground">@color/autofill_background_material_light</item>
+ </style>
+
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 542266f..cfc7f9f 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -99,6 +99,7 @@
private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
newHashSet(
Settings.Global.ACTIVITY_MANAGER_CONSTANTS,
+ Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED,
Settings.Global.ADB_ENABLED,
Settings.Global.ADD_USERS_WHEN_LOCKED,
Settings.Global.AIRPLANE_MODE_ON,
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index dba30f5..14b2e41 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -33,6 +33,7 @@
export_include_dirs: ["include"],
shared_libs: [
+ "libbase",
"libcutils",
"liblog",
],
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index 22b9709..3fee7e4 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -17,6 +17,7 @@
#include <inttypes.h>
+#include <android-base/file.h>
#include <android/util/protobuf.h>
#include <android/util/ProtoOutputStream.h>
#include <cutils/log.h>
@@ -467,19 +468,6 @@
return mBuffer.size();
}
-static bool write_all(int fd, uint8_t const* buf, size_t size)
-{
- while (size > 0) {
- ssize_t amt = ::write(fd, buf, size);
- if (amt < 0) {
- return false;
- }
- size -= amt;
- buf += amt;
- }
- return true;
-}
-
bool
ProtoOutputStream::flush(int fd)
{
@@ -488,7 +476,7 @@
EncodedBuffer::iterator it = mBuffer.begin();
while (it.readBuffer() != NULL) {
- if (!write_all(fd, it.readBuffer(), it.currentToRead())) return false;
+ if (!android::base::WriteFully(fd, it.readBuffer(), it.currentToRead())) return false;
it.rp()->move(it.currentToRead());
}
return true;
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 491f71e..db776c6 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -321,6 +321,7 @@
// TODO: reuse NetworkMonitor facilities for consistent captive portal detection.
new Thread(new Runnable() {
public void run() {
+ final Network network = ResolvUtil.makeNetworkWithPrivateDnsBypass(mNetwork);
// Give time for captive portal to open.
try {
Thread.sleep(1000);
@@ -329,7 +330,7 @@
HttpURLConnection urlConnection = null;
int httpResponseCode = 500;
try {
- urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
+ urlConnection = (HttpURLConnection) network.openConnection(mUrl);
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/PrinterHashMap.java
deleted file mode 100644
index 61956f6..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/PrinterHashMap.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printservice.recommendation.plugin.hp;
-
-import android.net.nsd.NsdServiceInfo;
-
-import java.util.HashMap;
-
-final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
- public static String getKey(NsdServiceInfo serviceInfo) {
- return serviceInfo.getServiceName();
- }
- public NsdServiceInfo addPrinter(NsdServiceInfo device) {
- return put(getKey(device), device);
- }
- public NsdServiceInfo removePrinter(NsdServiceInfo device) {
- return remove(getKey(device));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java
index 600af1f..9535ef0 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java
@@ -24,6 +24,7 @@
import com.android.printservice.recommendation.R;
import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
+import com.android.printservice.recommendation.util.PrinterHashMap;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -183,9 +184,7 @@
ArrayList<InetAddress> printerAddressess = new ArrayList<>();
for (PrinterHashMap oneVendorPrinters : mVendorHashMap.values()) {
- for (NsdServiceInfo printer : oneVendorPrinters.values()) {
- printerAddressess.add(printer.getHost());
- }
+ printerAddressess.addAll(oneVendorPrinters.getPrinterAddresses());
}
return printerAddressess;
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java
deleted file mode 100755
index b88c7c7..0000000
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/PrinterHashMap.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.printservice.recommendation.plugin.xerox;
-
-import android.net.nsd.NsdServiceInfo;
-
-import java.util.HashMap;
-
-final class PrinterHashMap extends HashMap<String, NsdServiceInfo> {
- public static String getKey(NsdServiceInfo serviceInfo) {
- return serviceInfo.getServiceName();
- }
-
- public NsdServiceInfo addPrinter(NsdServiceInfo device) {
- return put(getKey(device), device);
- }
-
- public NsdServiceInfo removePrinter(NsdServiceInfo device) {
- return remove(getKey(device));
- }
-}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java
index 4d0efd8..9ada969 100755
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java
@@ -22,6 +22,7 @@
import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer;
import com.android.printservice.recommendation.util.NsdResolveQueue;
+import com.android.printservice.recommendation.util.PrinterHashMap;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -195,12 +196,7 @@
}
public ArrayList<InetAddress> getPrinters() {
- ArrayList<InetAddress> printerAddresses = new ArrayList<>();
- for (NsdServiceInfo printer : mPrinterHashMap.values()) {
- printerAddresses.add(printer.getHost());
- }
-
- return printerAddresses;
+ return mPrinterHashMap.getPrinterAddresses();
}
}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
index c08ca6e..65cef94 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.GuardedBy;
@@ -27,9 +28,8 @@
import com.android.printservice.recommendation.PrintServicePlugin;
-import java.net.InetAddress;
-import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Set;
/**
@@ -55,9 +55,9 @@
boolean matchesCriteria(NsdServiceInfo nsdServiceInfo);
}
- /** Printer identifiers of the mPrinters found. */
+ /** Printers found. */
@GuardedBy("mLock")
- private final @NonNull HashSet<InetAddress> mPrinters;
+ private final @NonNull PrinterHashMap mPrinters;
/** Service types discovered by this plugin */
private final @NonNull HashSet<String> mServiceTypes;
@@ -97,7 +97,7 @@
mPrinterFilter = Preconditions.checkNotNull(printerFilter, "printerFilter");
mResolveQueue = NsdResolveQueue.getInstance();
- mPrinters = new HashSet<>();
+ mPrinters = new PrinterHashMap();
}
/**
@@ -107,6 +107,12 @@
return (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
}
+ private void onChanged() {
+ if (mCallback != null) {
+ mCallback.onChanged(mPrinters.getPrinterAddresses());
+ }
+ }
+
/**
* Start the discovery.
*
@@ -114,7 +120,8 @@
*/
public void start(@NonNull PrintServicePlugin.PrinterDiscoveryCallback callback) {
mCallback = callback;
- mCallback.onChanged(new ArrayList<>(mPrinters));
+
+ onChanged();
for (String serviceType : mServiceTypes) {
DiscoveryListenerMultiplexer.addListener(getNDSManager(), serviceType, this);
@@ -167,11 +174,12 @@
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (mPrinterFilter.matchesCriteria(serviceInfo)) {
+ if (!TextUtils.isEmpty(PrinterHashMap.getKey(serviceInfo))
+ && mPrinterFilter.matchesCriteria(serviceInfo)) {
if (mCallback != null) {
- boolean added = mPrinters.add(serviceInfo.getHost());
- if (added) {
- mCallback.onChanged(new ArrayList<>(mPrinters));
+ NsdServiceInfo old = mPrinters.addPrinter(serviceInfo);
+ if (!Objects.equals(old, serviceInfo)) {
+ onChanged();
}
}
}
@@ -181,26 +189,9 @@
@Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
- mResolveQueue.resolve(getNDSManager(), serviceInfo,
- new NsdManager.ResolveListener() {
- @Override
- public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
- Log.w(LOG_TAG, "Service lost: Could not resolve " + serviceInfo + ": "
- + errorCode);
- }
-
- @Override
- public void onServiceResolved(NsdServiceInfo serviceInfo) {
- if (mPrinterFilter.matchesCriteria(serviceInfo)) {
- if (mCallback != null) {
- boolean removed = mPrinters.remove(serviceInfo.getHost());
-
- if (removed) {
- mCallback.onChanged(new ArrayList<>(mPrinters));
- }
- }
- }
- }
- });
+ NsdServiceInfo oldAddress = mPrinters.removePrinter(serviceInfo);
+ if (oldAddress != null) {
+ onChanged();
+ }
}
-}
\ No newline at end of file
+}
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/PrinterHashMap.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/PrinterHashMap.java
new file mode 100644
index 0000000..ee35edb
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/PrinterHashMap.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printservice.recommendation.util;
+
+import android.net.nsd.NsdServiceInfo;
+import android.util.ArrayMap;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+
+/**
+ * Map to store {@link NsdServiceInfo} belonging to printers. If two infos have the same
+ * {@link PrinterHashMap#getKey(NsdServiceInfo) key} they are considered the same.
+ */
+public class PrinterHashMap {
+ private final ArrayMap<String, NsdServiceInfo> mPrinters = new ArrayMap<>();
+
+ /**
+ * Key uniquely identifying a printer.
+ *
+ * @param serviceInfo The service info describing the printer
+ *
+ * @return The key
+ */
+ public static String getKey(NsdServiceInfo serviceInfo) {
+ return serviceInfo.getServiceName();
+ }
+
+ /**
+ * Add a printer.
+ *
+ * @param device The service info of the printer
+ *
+ * @return The service info of the printer that was previously registered for the same key
+ */
+ public NsdServiceInfo addPrinter(NsdServiceInfo device) {
+ return mPrinters.put(getKey(device), device);
+ }
+
+ /**
+ * Remove a printer.
+ *
+ * @param device The service info of the printer
+ *
+ * @return The service info of the printer that was previously registered for the same key
+ */
+ public NsdServiceInfo removePrinter(NsdServiceInfo device) {
+ return mPrinters.remove(getKey(device));
+ }
+
+ /**
+ * @return the addresses of printers
+ */
+ public ArrayList<InetAddress> getPrinterAddresses() {
+ int numPrinters = mPrinters.size();
+ ArrayList<InetAddress> printerAddressess = new ArrayList<>(numPrinters);
+ for (int i = 0; i < numPrinters; i++) {
+ printerAddressess.add(mPrinters.valueAt(i).getHost());
+ }
+
+ return printerAddressess;
+ }
+
+ /**
+ * Remove all printers
+ */
+ public void clear() {
+ mPrinters.clear();
+ }
+
+ /**
+ * @return {@code} true iff the map is empty
+ */
+ public boolean isEmpty() {
+ return mPrinters.isEmpty();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index b976dd6..7f518c1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -46,6 +46,7 @@
import com.android.internal.widget.LockPatternUtils;
import java.util.List;
+import java.util.Objects;
/**
* Utility class to host methods usable in adding a restricted padlock icon and showing admin
@@ -90,29 +91,29 @@
// Restriction is not enforced.
return null;
} else if (enforcingUsers.size() > 1) {
- return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ return EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
}
final int restrictionSource = enforcingUsers.get(0).getUserRestrictionSource();
final int adminUserId = enforcingUsers.get(0).getUserHandle().getIdentifier();
-
if (restrictionSource == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) {
// Check if it is a profile owner of the user under consideration.
if (adminUserId == userId) {
- return getProfileOwner(context, adminUserId);
+ return getProfileOwner(context, userRestriction, adminUserId);
} else {
// Check if it is a profile owner of a managed profile of the current user.
// Otherwise it is in a separate user and we return a default EnforcedAdmin.
final UserInfo parentUser = um.getProfileParent(adminUserId);
return (parentUser != null && parentUser.id == userId)
- ? getProfileOwner(context, adminUserId)
- : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ ? getProfileOwner(context, userRestriction, adminUserId)
+ : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
}
} else if (restrictionSource == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
// When the restriction is enforced by device owner, return the device owner admin only
// if the admin is for the {@param userId} otherwise return a default EnforcedAdmin.
return adminUserId == userId
- ? getDeviceOwner(context) : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+ ? getDeviceOwner(context, userRestriction)
+ : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
}
// If the restriction is enforced by system then return null.
@@ -406,7 +407,6 @@
* or {@code null} if no quality requirements are set. If the requirements are set by
* multiple device admins, then the admin component will be set to {@code null} and userId to
* {@link UserHandle#USER_NULL}.
- *
*/
public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
final LockSettingCheck check =
@@ -518,6 +518,11 @@
}
public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
+ return getProfileOrDeviceOwner(context, null, userId);
+ }
+
+ public static EnforcedAdmin getProfileOrDeviceOwner(
+ Context context, String enforcedRestriction, int userId) {
if (userId == UserHandle.USER_NULL) {
return null;
}
@@ -528,18 +533,22 @@
}
ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
if (adminComponent != null) {
- return new EnforcedAdmin(adminComponent, userId);
+ return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
}
if (dpm.getDeviceOwnerUserId() == userId) {
adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
if (adminComponent != null) {
- return new EnforcedAdmin(adminComponent, userId);
+ return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
}
}
return null;
}
public static EnforcedAdmin getDeviceOwner(Context context) {
+ return getDeviceOwner(context, null);
+ }
+
+ private static EnforcedAdmin getDeviceOwner(Context context, String enforcedRestriction) {
final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm == null) {
@@ -547,12 +556,18 @@
}
ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
if (adminComponent != null) {
- return new EnforcedAdmin(adminComponent, dpm.getDeviceOwnerUserId());
+ return new EnforcedAdmin(
+ adminComponent, enforcedRestriction, dpm.getDeviceOwnerUserId());
}
return null;
}
private static EnforcedAdmin getProfileOwner(Context context, int userId) {
+ return getProfileOwner(context, null, userId);
+ }
+
+ private static EnforcedAdmin getProfileOwner(
+ Context context, String enforcedRestriction, int userId) {
if (userId == UserHandle.USER_NULL) {
return null;
}
@@ -563,7 +578,7 @@
}
ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
if (adminComponent != null) {
- return new EnforcedAdmin(adminComponent, userId);
+ return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
}
return null;
}
@@ -626,6 +641,7 @@
&& isCurrentUserOrProfile(context, admin.userId)) {
targetUserId = admin.userId;
}
+ intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
context.startActivityAsUser(intent, new UserHandle(targetUserId));
}
@@ -700,53 +716,71 @@
}
public static class EnforcedAdmin {
+ @Nullable
public ComponentName component = null;
+ /**
+ * The restriction enforced by admin. It could be any user restriction or policy like
+ * {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}.
+ */
+ @Nullable
+ public String enforcedRestriction = null;
public int userId = UserHandle.USER_NULL;
// We use this to represent the case where a policy is enforced by multiple admins.
public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin();
+ public static EnforcedAdmin createDefaultEnforcedAdminWithRestriction(
+ String enforcedRestriction) {
+ EnforcedAdmin enforcedAdmin = new EnforcedAdmin();
+ enforcedAdmin.enforcedRestriction = enforcedRestriction;
+ return enforcedAdmin;
+ }
+
public EnforcedAdmin(ComponentName component, int userId) {
this.component = component;
this.userId = userId;
}
+ public EnforcedAdmin(ComponentName component, String enforcedRestriction, int userId) {
+ this.component = component;
+ this.enforcedRestriction = enforcedRestriction;
+ this.userId = userId;
+ }
+
public EnforcedAdmin(EnforcedAdmin other) {
if (other == null) {
throw new IllegalArgumentException();
}
this.component = other.component;
+ this.enforcedRestriction = other.enforcedRestriction;
this.userId = other.userId;
}
- public EnforcedAdmin() {}
+ public EnforcedAdmin() {
+ }
@Override
- public boolean equals(Object object) {
- if (object == this) return true;
- if (!(object instanceof EnforcedAdmin)) return false;
- EnforcedAdmin other = (EnforcedAdmin) object;
- if (userId != other.userId) {
- return false;
- }
- if ((component == null && other.component == null) ||
- (component != null && component.equals(other.component))) {
- return true;
- }
- return false;
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ EnforcedAdmin that = (EnforcedAdmin) o;
+ return userId == that.userId &&
+ Objects.equals(component, that.component) &&
+ Objects.equals(enforcedRestriction, that.enforcedRestriction);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(component, enforcedRestriction, userId);
}
@Override
public String toString() {
- return "EnforcedAdmin{component=" + component + ",userId=" + userId + "}";
- }
-
- public void copyTo(EnforcedAdmin other) {
- if (other == null) {
- throw new IllegalArgumentException();
- }
- other.component = component;
- other.userId = userId;
+ return "EnforcedAdmin{" +
+ "component=" + component +
+ ", enforcedRestriction='" + enforcedRestriction +
+ ", userId=" + userId +
+ '}';
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
index 246ca47..afc08f4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/DefaultAppInfo.java
@@ -40,18 +40,18 @@
public final ComponentName componentName;
public final PackageItemInfo packageItemInfo;
public final String summary;
- protected final PackageManagerWrapper mPm;
+ protected final PackageManager mPm;
private final Context mContext;
- public DefaultAppInfo(Context context, PackageManagerWrapper pm, int uid, ComponentName cn) {
+ public DefaultAppInfo(Context context, PackageManager pm, int uid, ComponentName cn) {
this(context, pm, uid, cn, null /* summary */, true /* enabled */);
}
- public DefaultAppInfo(Context context, PackageManagerWrapper pm, PackageItemInfo info) {
+ public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info) {
this(context, pm, info, null /* summary */, true /* enabled */);
}
- public DefaultAppInfo(Context context, PackageManagerWrapper pm, int uid, ComponentName cn,
+ public DefaultAppInfo(Context context, PackageManager pm, int uid, ComponentName cn,
String summary, boolean enabled) {
super(enabled);
mContext = context;
@@ -62,7 +62,7 @@
this.summary = summary;
}
- public DefaultAppInfo(Context context, PackageManagerWrapper pm, PackageItemInfo info,
+ public DefaultAppInfo(Context context, PackageManager pm, PackageItemInfo info,
String summary, boolean enabled) {
super(enabled);
mContext = context;
@@ -79,17 +79,17 @@
try {
final ComponentInfo componentInfo = getComponentInfo();
if (componentInfo != null) {
- return componentInfo.loadLabel(mPm.getPackageManager());
+ return componentInfo.loadLabel(mPm);
} else {
final ApplicationInfo appInfo = mPm.getApplicationInfoAsUser(
componentName.getPackageName(), 0, userId);
- return appInfo.loadLabel(mPm.getPackageManager());
+ return appInfo.loadLabel(mPm);
}
} catch (PackageManager.NameNotFoundException e) {
return null;
}
} else if (packageItemInfo != null) {
- return packageItemInfo.loadLabel(mPm.getPackageManager());
+ return packageItemInfo.loadLabel(mPm);
} else {
return null;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
index 3c3c70a..454d1dc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
@@ -32,8 +32,6 @@
import android.provider.Settings;
import android.util.Slog;
-import com.android.settingslib.wrapper.PackageManagerWrapper;
-
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -127,8 +125,7 @@
mServices.clear();
final int user = ActivityManager.getCurrentUser();
- final PackageManagerWrapper pmWrapper =
- new PackageManagerWrapper(mContext.getPackageManager());
+ final PackageManager pmWrapper = mContext.getPackageManager();
List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser(
new Intent(mIntentAction),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 6b99024..6272954 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -20,7 +20,6 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothCodecConfig;
-import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
@@ -28,9 +27,7 @@
import android.os.ParcelUuid;
import android.util.Log;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.R;
-import com.android.settingslib.wrapper.BluetoothA2dpWrapper;
import java.util.ArrayList;
import java.util.Arrays;
@@ -43,7 +40,6 @@
private Context mContext;
private BluetoothA2dp mService;
- private BluetoothA2dpWrapper mServiceWrapper;
private boolean mIsProfileReady;
private final LocalBluetoothAdapter mLocalAdapter;
@@ -67,7 +63,6 @@
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (V) Log.d(TAG,"Bluetooth service connected");
mService = (BluetoothA2dp) proxy;
- mServiceWrapper = new BluetoothA2dpWrapper(mService);
// We just bound to the service, so refresh the UI for any connected A2DP devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
while (!deviceList.isEmpty()) {
@@ -105,11 +100,6 @@
BluetoothProfile.A2DP);
}
- @VisibleForTesting
- void setBluetoothA2dpWrapper(BluetoothA2dpWrapper wrapper) {
- mServiceWrapper = wrapper;
- }
-
public boolean isConnectable() {
return true;
}
@@ -203,12 +193,12 @@
}
public boolean supportsHighQualityAudio(BluetoothDevice device) {
- int support = mServiceWrapper.supportsOptionalCodecs(device);
+ int support = mService.supportsOptionalCodecs(device);
return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
}
public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
- int enabled = mServiceWrapper.getOptionalCodecsEnabled(device);
+ int enabled = mService.getOptionalCodecsEnabled(device);
if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) {
return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED;
} else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED &&
@@ -219,8 +209,8 @@
return true;
}
BluetoothCodecConfig codecConfig = null;
- if (mServiceWrapper.getCodecStatus(device) != null) {
- codecConfig = mServiceWrapper.getCodecStatus(device).getCodecConfig();
+ if (mService.getCodecStatus(device) != null) {
+ codecConfig = mService.getCodecStatus(device).getCodecConfig();
}
if (codecConfig != null) {
return !codecConfig.isMandatoryCodec();
@@ -233,7 +223,7 @@
int prefValue = enabled
? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
: BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
- mServiceWrapper.setOptionalCodecsEnabled(device, prefValue);
+ mService.setOptionalCodecsEnabled(device, prefValue);
if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
return;
}
@@ -253,8 +243,8 @@
// We want to get the highest priority codec, since that's the one that will be used with
// this device, and see if it is high-quality (ie non-mandatory).
BluetoothCodecConfig[] selectable = null;
- if (mServiceWrapper.getCodecStatus(device) != null) {
- selectable = mServiceWrapper.getCodecStatus(device).getCodecsSelectableCapabilities();
+ if (mService.getCodecStatus(device) != null) {
+ selectable = mService.getCodecStatus(device).getCodecsSelectableCapabilities();
// To get the highest priority, we sort in reverse.
Arrays.sort(selectable,
(a, b) -> {
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
index 113256f..e2faf6a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
@@ -354,20 +354,15 @@
return;
}
- if (userInfo.isGuest()) {
- switchToGuest(userInfo.name);
- return;
- }
-
switchToUserId(userInfo.id);
}
/**
- * Creates a guest session and switches into the guest session.
+ * Creates a new guest session and switches into the guest session.
*
* @param guestName Username for the guest user.
*/
- public void switchToGuest(String guestName) {
+ public void startNewGuestSession(String guestName) {
UserInfo guest = mUserManager.createGuest(mContext, guestName);
if (guest == null) {
// Couldn't create user, most likely because there are too many, but we haven't
@@ -375,6 +370,7 @@
Log.w(TAG, "can't create user.");
return;
}
+ assignDefaultIcon(guest);
switchToUserId(guest.id);
}
@@ -417,6 +413,27 @@
mUserManager.setUserName(user.id, name);
}
+ /**
+ * Gets a bitmap representing the user's default avatar.
+ *
+ * @param userInfo User whose avatar should be returned.
+ * @return Default user icon
+ */
+ public Bitmap getUserDefaultIcon(UserInfo userInfo) {
+ return UserIcons.convertToBitmap(
+ UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+ }
+
+ /**
+ * Gets a bitmap representing the default icon for a Guest user.
+ *
+ * @return Degault guest icon
+ */
+ public Bitmap getGuestDefaultIcon() {
+ return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
+ mContext.getResources(), UserHandle.USER_NULL, false));
+ }
+
private void registerReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_REMOVED);
@@ -435,8 +452,7 @@
* @return Bitmap that has been assigned to the user.
*/
private Bitmap assignDefaultIcon(UserInfo userInfo) {
- Bitmap bitmap = UserIcons.convertToBitmap(
- UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+ Bitmap bitmap = userInfo.isGuest() ? getGuestDefaultIcon() : getUserDefaultIcon(userInfo);
mUserManager.setUserIcon(userInfo.id, bitmap);
return bitmap;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wrapper/BluetoothA2dpWrapper.java b/packages/SettingsLib/src/com/android/settingslib/wrapper/BluetoothA2dpWrapper.java
deleted file mode 100644
index 17e3401..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/wrapper/BluetoothA2dpWrapper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.wrapper;
-
-import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothCodecStatus;
-import android.bluetooth.BluetoothDevice;
-
-/**
- * This class replicates some methods of android.bluetooth.BluetoothA2dp that are new and not
- * yet available in our current version of Robolectric. It provides a thin wrapper to call the real
- * methods in production and a mock in tests.
- */
-public class BluetoothA2dpWrapper {
-
- private BluetoothA2dp mService;
-
- public BluetoothA2dpWrapper(BluetoothA2dp service) {
- mService = service;
- }
-
- /**
- * @return the real {@code BluetoothA2dp} object
- */
- public BluetoothA2dp getService() {
- return mService;
- }
-
- /**
- * Wraps {@code BluetoothA2dp.getCodecStatus}
- */
- public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
- return mService.getCodecStatus(device);
- }
-
- /**
- * Wraps {@code BluetoothA2dp.supportsOptionalCodecs}
- */
- public int supportsOptionalCodecs(BluetoothDevice device) {
- return mService.supportsOptionalCodecs(device);
- }
-
- /**
- * Wraps {@code BluetoothA2dp.getOptionalCodecsEnabled}
- */
- public int getOptionalCodecsEnabled(BluetoothDevice device) {
- return mService.getOptionalCodecsEnabled(device);
- }
-
- /**
- * Wraps {@code BluetoothA2dp.setOptionalCodecsEnabled}
- */
- public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
- mService.setOptionalCodecsEnabled(device, value);
- }
-}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java b/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java
index 235daf2..4e22473 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java
@@ -35,6 +35,8 @@
* and the PackageManager. This class only provides access to the minimum number of functions from
* the PackageManager needed for DeletionHelper to work.
*/
+@Deprecated
+// Please replace with android.content.pm.PackageManager
public class PackageManagerWrapper {
private final PackageManager mPm;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
index 15f7770..54510b2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -247,13 +247,13 @@
}
@Test
- public void switchToGuest() {
- mHelper.switchToGuest("Test Guest");
+ public void startNewGuestSession() {
+ mHelper.startNewGuestSession("Test Guest");
verify(mUserManager).createGuest(mContext, "Test Guest");
UserInfo guestInfo = new UserInfo(21, "Test Guest", UserInfo.FLAG_GUEST);
when(mUserManager.createGuest(mContext, "Test Guest")).thenReturn(guestInfo);
- mHelper.switchToGuest("Test Guest");
+ mHelper.startNewGuestSession("Test Guest");
verify(mActivityManager).switchUser(21);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 5f60868..710dbc22 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -32,6 +32,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.os.UserHandle;
import android.os.UserManager;
import org.junit.Before;
@@ -42,6 +43,7 @@
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
+import java.util.Collections;
@RunWith(SettingsLibRobolectricTestRunner.class)
public class RestrictedLockUtilsTest {
@@ -77,6 +79,42 @@
}
@Test
+ public void checkIfRestrictionEnforced_deviceOwner() {
+ UserManager.EnforcingUser enforcingUser = new UserManager.EnforcingUser(mUserId,
+ UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
+ final String userRestriction = UserManager.DISALLOW_UNINSTALL_APPS;
+ when(mUserManager.getUserRestrictionSources(userRestriction,
+ UserHandle.of(mUserId))).
+ thenReturn(Collections.singletonList(enforcingUser));
+ setUpDeviceOwner(mAdmin1);
+
+ EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+ userRestriction, mUserId);
+
+ assertThat(enforcedAdmin).isNotNull();
+ assertThat(enforcedAdmin.enforcedRestriction).isEqualTo(userRestriction);
+ assertThat(enforcedAdmin.component).isEqualTo(mAdmin1);
+ }
+
+ @Test
+ public void checkIfRestrictionEnforced_profileOwner() {
+ UserManager.EnforcingUser enforcingUser = new UserManager.EnforcingUser(mUserId,
+ UserManager.RESTRICTION_SOURCE_PROFILE_OWNER);
+ final String userRestriction = UserManager.DISALLOW_UNINSTALL_APPS;
+ when(mUserManager.getUserRestrictionSources(userRestriction,
+ UserHandle.of(mUserId))).
+ thenReturn(Collections.singletonList(enforcingUser));
+ setUpProfileOwner(mAdmin1, mUserId);
+
+ EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+ userRestriction, mUserId);
+
+ assertThat(enforcedAdmin).isNotNull();
+ assertThat(enforcedAdmin.enforcedRestriction).isEqualTo(userRestriction);
+ assertThat(enforcedAdmin.component).isEqualTo(mAdmin1);
+ }
+
+ @Test
public void checkIfDevicePolicyServiceDisabled_noEnforceAdminForManagedProfile() {
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(null);
final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfAccountManagementDisabled(
@@ -263,4 +301,12 @@
when(mDevicePolicyManager.getActiveAdminsAsUser(userId))
.thenReturn(Arrays.asList(activeAdmins));
}
+
+ private void setUpDeviceOwner(ComponentName admin) {
+ when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(admin);
+ }
+
+ private void setUpProfileOwner(ComponentName admin, int userId) {
+ when(mDevicePolicyManager.getProfileOwnerAsUser(userId)).thenReturn(admin);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
index 6a161d0..01f0d78 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
@@ -33,7 +33,6 @@
import android.graphics.drawable.Drawable;
import com.android.settingslib.SettingsLibRobolectricTestRunner;
-import com.android.settingslib.wrapper.PackageManagerWrapper;
import org.junit.Before;
import org.junit.Test;
@@ -41,7 +40,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
@RunWith(SettingsLibRobolectricTestRunner.class)
public class DefaultAppInfoTest {
@@ -53,8 +51,6 @@
@Mock
private PackageManager mPackageManager;
@Mock
- private PackageManagerWrapper mPackageManagerWrapper;
- @Mock
private ApplicationInfo mApplicationInfo;
@Mock
private Drawable mIcon;
@@ -67,8 +63,7 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mPackageManager).when(mContext).getPackageManager();
- when(mPackageManagerWrapper.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManagerWrapper.getApplicationInfoAsUser(anyString(), anyInt(),
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(),
anyInt())).thenReturn(mApplicationInfo);
when(mPackageManager.loadUnbadgedItemIcon(mPackageItemInfo, mApplicationInfo)).thenReturn(
mIcon);
@@ -77,7 +72,7 @@
@Test
public void initInfoWithActivityInfo_shouldLoadInfo() {
mPackageItemInfo.packageName = "test";
- mInfo = new DefaultAppInfo(mContext, mPackageManagerWrapper, mPackageItemInfo);
+ mInfo = new DefaultAppInfo(mContext, mPackageManager, mPackageItemInfo);
mInfo.loadLabel();
Drawable icon = mInfo.loadIcon();
@@ -90,7 +85,7 @@
public void initInfoWithComponent_shouldLoadInfo() {
when(mComponentName.getPackageName()).thenReturn("com.android.settings");
- mInfo = new DefaultAppInfo(mContext, mPackageManagerWrapper, 0 /* uid */, mComponentName);
+ mInfo = new DefaultAppInfo(mContext, mPackageManager, 0 /* uid */, mComponentName);
mInfo.getKey();
verify(mComponentName).flattenToString();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index 334ea16..ef13a5f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -31,7 +31,6 @@
import android.content.res.Resources;
import com.android.settingslib.R;
-import com.android.settingslib.wrapper.BluetoothA2dpWrapper;
import org.junit.Before;
import org.junit.Test;
@@ -49,7 +48,6 @@
@Mock LocalBluetoothProfileManager mProfileManager;
@Mock BluetoothDevice mDevice;
@Mock BluetoothA2dp mBluetoothA2dp;
- @Mock BluetoothA2dpWrapper mBluetoothA2dpWrapper;
BluetoothProfile.ServiceListener mServiceListener;
A2dpProfile mProfile;
@@ -68,31 +66,30 @@
mProfile = new A2dpProfile(mContext, mAdapter, mDeviceManager, mProfileManager);
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
- mProfile.setBluetoothA2dpWrapper(mBluetoothA2dpWrapper);
}
@Test
public void supportsHighQualityAudio() {
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue();
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
}
@Test
public void isHighQualityAudioEnabled() {
- when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
- when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
@@ -100,23 +97,23 @@
// then isHighQualityAudioEnabled() should return true or false based on whether optional
// codecs are supported. If the device is connected then we should ask it directly, but if
// the device isn't connected then rely on the stored pref about such support.
- when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+ when(mBluetoothA2dp.getOptionalCodecsEnabled(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
BluetoothProfile.STATE_DISCONNECTED);
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
BluetoothProfile.STATE_CONNECTED);
BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
- when(mBluetoothA2dpWrapper.getCodecStatus(mDevice)).thenReturn(status);
+ when(mBluetoothA2dp.getCodecStatus(mDevice)).thenReturn(status);
BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
when(status.getCodecConfig()).thenReturn(config);
when(config.isMandatoryCodec()).thenReturn(false);
@@ -151,14 +148,14 @@
// Most tests want to simulate optional codecs being supported by the device, so do that
// by default here.
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
}
@Test
public void getLableCodecsNotSupported() {
setupLabelTest();
- when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+ when(mBluetoothA2dp.supportsOptionalCodecs(any())).thenReturn(
BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
}
@@ -179,7 +176,7 @@
BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
BluetoothCodecConfig[] configs = {config};
- when(mBluetoothA2dpWrapper.getCodecStatus(mDevice)).thenReturn(status);
+ when(mBluetoothA2dp.getCodecStatus(mDevice)).thenReturn(status);
when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
when(config.isMandatoryCodec()).thenReturn(true);
@@ -194,7 +191,7 @@
BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
BluetoothCodecConfig[] configs = {config};
- when(mBluetoothA2dpWrapper.getCodecStatus(mDevice)).thenReturn(status);
+ when(mBluetoothA2dp.getCodecStatus(mDevice)).thenReturn(status);
when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
when(config.isMandatoryCodec()).thenReturn(false);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
index f2ea3a4..890abef 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
@@ -185,12 +185,7 @@
mHelper.switchToUser(createUserInfoForId(20));
assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isFalse();
- // Switching to Guest calls createGuest.
- UserInfo guestInfo = new UserInfo(21, "Test Guest", UserInfo.FLAG_GUEST);
- mHelper.switchToUser(guestInfo);
- verify(mUserManager).createGuest(mContext, "Test Guest");
-
- // Switching to non-current, non-guest user, simply calls switchUser.
+ // Switching to non-foreground user, simply calls switchUser.
UserInfo userToSwitchTo = new UserInfo(22, "Test User", 0);
mHelper.switchToUser(userToSwitchTo);
assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
index db57fd1..ccde571 100644
--- a/packages/SettingsProvider/Android.mk
+++ b/packages/SettingsProvider/Android.mk
@@ -3,6 +3,8 @@
LOCAL_MODULE_TAGS := optional
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/providers/settings/EventLogTags.logtags
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 4c98bb8..7a994a8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -17,7 +17,6 @@
package com.android.providers.settings;
import android.os.Process;
-import com.android.internal.R;
import com.android.internal.app.LocalePicker;
import com.android.internal.annotations.VisibleForTesting;
@@ -30,13 +29,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
-import android.hardware.display.DisplayManager;
import android.icu.util.ULocale;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.net.Uri;
-import android.os.IPowerManager;
import android.os.LocaleList;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -46,16 +43,16 @@
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.Slog;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
public class SettingsHelper {
private static final String TAG = "SettingsHelper";
private static final String SILENT_RINGTONE = "_silent";
+ private static final float FLOAT_TOLERANCE = 0.01f;
+
private Context mContext;
private AudioManager mAudioManager;
private TelephonyManager mTelephonyManager;
@@ -259,9 +256,14 @@
case Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES:
case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES:
case Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER:
- case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE:
return !TextUtils.isEmpty(Settings.Secure.getString(
mContext.getContentResolver(), name));
+ case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE:
+ float defaultScale = mContext.getResources().getFraction(
+ R.fraction.def_accessibility_display_magnification_scale, 1, 1);
+ float currentScale = Settings.Secure.getFloat(
+ mContext.getContentResolver(), name, defaultScale);
+ return Math.abs(currentScale - defaultScale) >= FLOAT_TOLERANCE;
case Settings.System.FONT_SCALE:
return Settings.System.getFloat(mContext.getContentResolver(), name, 1.0f) != 1.0f;
default:
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
index bd5b1f2..0d681ed 100644
--- a/packages/SettingsProvider/test/Android.mk
+++ b/packages/SettingsProvider/test/Android.mk
@@ -14,6 +14,10 @@
LOCAL_JAVA_LIBRARIES := android.test.base
+LOCAL_RESOURCE_DIR := frameworks/base/packages/SettingsProvider/res
+
+LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.providers.settings
+
LOCAL_PACKAGE_NAME := SettingsProviderTest
LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java
new file mode 100644
index 0000000..b5324e5
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.settings;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SettingsHelper#restoreValue(Context, ContentResolver, ContentValues, Uri,
+ * String, String, int)}. Specifically verifies that we restore critical accessibility settings only
+ * if the user has not already configured these in SUW.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SettingsHelperRestoreTest {
+ private static final float FLOAT_TOLERANCE = 0.01f;
+
+ private Context mContext;
+ private ContentResolver mContentResolver;
+ private SettingsHelper mSettingsHelper;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getContext();
+ mContentResolver = mContext.getContentResolver();
+ mSettingsHelper = new SettingsHelper(mContext);
+ }
+
+ /** Tests for {@link Settings.Secure#ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE}. */
+ @Test
+ public void
+ testRestoreAccessibilityDisplayMagnificationScale_alreadyConfigured_doesNotRestoreValue()
+ throws Exception {
+ float defaultSettingValue = setDefaultAccessibilityDisplayMagnificationScale();
+ String settingName = Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE;
+ float restoreSettingValue = defaultSettingValue + 0.5f;
+
+ // Simulate already configuring setting via SUW.
+ float configuredSettingValue = defaultSettingValue + 1.0f;
+ Settings.Secure.putFloat(mContentResolver, settingName, configuredSettingValue);
+
+ mSettingsHelper.restoreValue(
+ mContext,
+ mContentResolver,
+ new ContentValues(2),
+ Settings.Secure.getUriFor(settingName),
+ settingName,
+ String.valueOf(restoreSettingValue),
+ Build.VERSION.SDK_INT);
+
+ assertEquals(
+ configuredSettingValue,
+ Settings.Secure.getFloat(mContentResolver, settingName),
+ FLOAT_TOLERANCE);
+ }
+
+ @Test
+ public void
+ testRestoreAccessibilityDisplayMagnificationScale_notAlreadyConfigured_restoresValue()
+ throws Exception {
+ float defaultSettingValue = setDefaultAccessibilityDisplayMagnificationScale();
+ String settingName = Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE;
+ float restoreSettingValue = defaultSettingValue + 0.5f;
+
+ mSettingsHelper.restoreValue(
+ mContext,
+ mContentResolver,
+ new ContentValues(2),
+ Settings.Secure.getUriFor(settingName),
+ settingName,
+ String.valueOf(restoreSettingValue),
+ Build.VERSION.SDK_INT);
+
+ assertEquals(
+ restoreSettingValue,
+ Settings.Secure.getFloat(mContentResolver, settingName),
+ FLOAT_TOLERANCE);
+ }
+
+ /**
+ * Simulate {@link Settings.Secure#ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE} value at boot by
+ * loading the default.
+ *
+ * @return the default value.
+ */
+ private float setDefaultAccessibilityDisplayMagnificationScale() {
+ float defaultSettingValue =
+ mContext.getResources()
+ .getFraction(
+ R.fraction.def_accessibility_display_magnification_scale, 1, 1);
+ Settings.Secure.putFloat(
+ mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+ defaultSettingValue);
+ return defaultSettingValue;
+ }
+}
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 5f73bef..4301fdb 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -18,13 +18,15 @@
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/quick_qs_status_icons"
android:layout_width="match_parent"
- android:layout_height="20dp"
+ android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="14dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="@dimen/notification_side_paddings"
+ android:layout_marginStart="@dimen/status_bar_padding_start"
+ android:layout_marginEnd="@dimen/status_bar_padding_end"
android:layout_below="@id/quick_status_bar_system_icons"
- android:paddingEnd="@dimen/status_bar_padding_end" >
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:minHeight="20dp" >
<com.android.systemui.statusbar.policy.DateView
android:id="@+id/date"
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 54baa4a..0892f73 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -45,14 +45,16 @@
android:layout_width="@dimen/qs_header_alarm_icon_size"
android:layout_height="@dimen/qs_header_alarm_icon_size"
android:src="@drawable/stat_sys_alarm"
- android:tint="?android:attr/textColorPrimary" />
+ android:tint="?android:attr/textColorPrimary"
+ android:visibility="gone"/>
<TextView
android:id="@+id/next_alarm_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
- android:textAppearance="@style/TextAppearance.QS.TileLabel" />
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:visibility="gone"/>
<View
android:id="@+id/status_separator"
@@ -61,20 +63,23 @@
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="@android:color/white"
- android:backgroundTint="?android:attr/textColorPrimary" />
+ android:backgroundTint="?android:attr/textColorPrimary"
+ android:visibility="gone"/>
<ImageView
android:id="@+id/ringer_mode_icon"
android:layout_width="@dimen/qs_header_alarm_icon_size"
android:layout_height="@dimen/qs_header_alarm_icon_size"
- android:tint="?android:attr/textColorPrimary" />
+ android:tint="?android:attr/textColorPrimary"
+ android:visibility="gone"/>
<TextView
android:id="@+id/ringer_mode_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
- android:textAppearance="@style/TextAppearance.QS.TileLabel" />
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:visibility="gone"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index a9fe8620..d40534e 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -20,15 +20,12 @@
android:id="@+id/quick_status_bar_system_icons"
android:layout_width="match_parent"
android:layout_height="@*android:dimen/quick_qs_offset_height"
- android:layout_marginRight="@dimen/notification_side_paddings"
- android:layout_marginLeft="@dimen/notification_side_paddings"
- android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
+ android:orientation="horizontal"
android:paddingStart="@dimen/status_bar_padding_start"
- android:paddingEnd="@dimen/status_bar_padding_end"
- android:orientation="horizontal">
+ android:paddingEnd="@dimen/status_bar_padding_end" >
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
diff --git a/packages/SystemUI/res/layout/volume_dnd_icon.xml b/packages/SystemUI/res/layout/volume_dnd_icon.xml
index acf9aed..215b230 100644
--- a/packages/SystemUI/res/layout/volume_dnd_icon.xml
+++ b/packages/SystemUI/res/layout/volume_dnd_icon.xml
@@ -15,16 +15,16 @@
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/volume_dialog_panel_width"
- android:layout_height="wrap_content">
+ android:layout_width="14dp"
+ android:layout_height="14dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginRight="6dp"
+ android:layout_gravity="right|top">
<ImageView
android:id="@+id/dnd_icon"
- android:layout_width="14dp"
- android:layout_height="14dp"
- android:layout_marginTop="6dp"
- android:layout_marginRight="6dp"
- android:layout_gravity="right|top"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:src="@drawable/ic_dnd"
android:tint="?android:attr/textColorTertiary"/>
</FrameLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 26c7858..ac9fb2b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -326,7 +326,7 @@
<dimen name="pull_span_min">25dp</dimen>
<dimen name="qs_tile_height">106dp</dimen>
- <dimen name="qs_tile_layout_margin_side">9dp</dimen>
+ <dimen name="qs_tile_layout_margin_side">6dp</dimen>
<dimen name="qs_tile_margin_horizontal">18dp</dimen>
<dimen name="qs_tile_margin_vertical">24dp</dimen>
<dimen name="qs_tile_margin_top_bottom">12dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d82b00c..697ab06 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2223,4 +2223,6 @@
<!-- An action on the dialog that tells that scheduled (i.e. automatic) battery saver: user acknowledges and closes the dialog. [CHAR LIMIT=NONE]-->
<string name="auto_saver_okay_action">Got it</string>
+ <!-- URl of the webpage that explains battery saver. -->
+ <string name="help_uri_battery_saver_learn_more_link_target" translatable="false"></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 8cc47eb..5b76627 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -19,17 +19,29 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioAttributes;
+import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
+import android.text.Annotation;
+import android.text.Layout;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.URLSpan;
+import android.util.Log;
import android.util.Slog;
+import android.view.View;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.settingslib.Utils;
@@ -42,6 +54,8 @@
import java.io.PrintWriter;
import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.Objects;
public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private static final String TAG = PowerUI.TAG + ".Notification";
@@ -87,6 +101,8 @@
private static final String SETTINGS_ACTION_OPEN_BATTERY_SAVER_SETTING =
"android.settings.BATTERY_SAVER_SETTINGS";
+ private static final String BATTERY_SAVER_DESCRIPTION_URL_KEY = "url";
+
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
@@ -463,7 +479,16 @@
if (mSaverConfirmation != null) return;
final SystemUIDialog d = new SystemUIDialog(mContext);
d.setTitle(R.string.battery_saver_confirmation_title);
- d.setMessage(com.android.internal.R.string.battery_saver_description);
+ d.setMessage(getBatterySaverDescription());
+
+ // Sad hack for http://b/78261259 and http://b/78298335. Otherwise "Battery" may be split
+ // into "Bat-tery".
+ if (isEnglishLocale()) {
+ d.setMessageHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE);
+ }
+ // We need to set LinkMovementMethod to make the link clickable.
+ d.setMessageMovementMethod(LinkMovementMethod.getInstance());
+
d.setNegativeButton(android.R.string.cancel, null);
d.setPositiveButton(R.string.battery_saver_confirmation_ok,
(dialog, which) -> setSaverMode(true, false));
@@ -473,6 +498,79 @@
mSaverConfirmation = d;
}
+ private boolean isEnglishLocale() {
+ return Objects.equals(Locale.getDefault().getLanguage(),
+ Locale.ENGLISH.getLanguage());
+ }
+
+ /**
+ * Generates the message for the "want to start battery saver?" dialog with a "learn more" link.
+ */
+ private CharSequence getBatterySaverDescription() {
+ final String learnMoreUrl = mContext.getText(
+ R.string.help_uri_battery_saver_learn_more_link_target).toString();
+
+ // If there's no link, use the string with no "learn more".
+ if (TextUtils.isEmpty(learnMoreUrl)) {
+ return mContext.getText(
+ com.android.internal.R.string.battery_saver_description);
+ }
+
+ // If we have a link, use the string with the "learn more" link.
+ final CharSequence rawText = mContext.getText(
+ com.android.internal.R.string.battery_saver_description_with_learn_more);
+ final SpannableString message = new SpannableString(rawText);
+ final SpannableStringBuilder builder = new SpannableStringBuilder(message);
+
+ // Look for the "learn more" part of the string, and set a URL span on it.
+ // We use a customized URLSpan to add FLAG_RECEIVER_FOREGROUND to the intent, and
+ // also to close the dialog.
+ for (Annotation annotation : message.getSpans(0, message.length(), Annotation.class)) {
+ final String key = annotation.getValue();
+
+ if (!BATTERY_SAVER_DESCRIPTION_URL_KEY.equals(key)) {
+ continue;
+ }
+ final int start = message.getSpanStart(annotation);
+ final int end = message.getSpanEnd(annotation);
+
+ // Replace the "learn more" with a custom URL span, with
+ // - No underline.
+ // - When clicked, close the dialog and the notification shade.
+ final URLSpan urlSpan = new URLSpan(learnMoreUrl) {
+ @Override
+ public void updateDrawState(TextPaint ds) {
+ super.updateDrawState(ds);
+ ds.setUnderlineText(false);
+ }
+
+ @Override
+ public void onClick(View widget) {
+ // Close the parent dialog.
+ if (mSaverConfirmation != null) {
+ mSaverConfirmation.dismiss();
+ }
+ // Also close the notification shade, if it's open.
+ mContext.sendBroadcast(
+ new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
+ .setFlags(Intent.FLAG_RECEIVER_FOREGROUND));
+
+ final Uri uri = Uri.parse(getURL());
+ Context context = widget.getContext();
+ Intent intent = new Intent(Intent.ACTION_VIEW, uri)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Activity was not found for intent, " + intent.toString());
+ }
+ }
+ };
+ builder.setSpan(urlSpan, start, end, message.getSpanFlags(urlSpan));
+ }
+ return builder;
+ }
+
private void showAutoSaverEnabledConfirmation() {
if (mSaverEnabledConfirmation != null) return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index a44f9433..d8bf990 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -40,7 +40,7 @@
private int mHeightOverride = -1;
private QSPanel mQSPanel;
private View mQSDetail;
- private View mHeader;
+ private QuickStatusBarHeader mHeader;
private float mQsExpansion;
private QSCustomizer mQSCustomizer;
private View mQSFooter;
@@ -178,7 +178,7 @@
setMargins(mBackground);
setMargins(mQSFooter);
mQSPanel.setMargins(mSideMargins);
- setMargins(mHeader);
+ mHeader.setMargins(mSideMargins);
}
private void setMargins(View view) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 7a24a60..3d326ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -41,6 +41,7 @@
import android.view.View;
import android.view.WindowInsets;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -592,4 +593,16 @@
public static float getColorIntensity(@ColorInt int color) {
return color == Color.WHITE ? 0 : 1;
}
+
+ public void setMargins(int sideMargins) {
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getChildAt(i);
+ if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel) {
+ continue;
+ }
+ RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
+ lp.leftMargin = sideMargins;
+ lp.rightMargin = sideMargins;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index a950cd5..a54c778 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -207,7 +207,7 @@
// If the user selects Guest, start the guest session.
if (userRecord.mIsStartGuestSession) {
- mUserManagerHelper.switchToGuest(mGuestName);
+ mUserManagerHelper.startNewGuestSession(mGuestName);
return;
}
@@ -241,8 +241,7 @@
private Bitmap getUserRecordIcon(UserRecord userRecord) {
if (userRecord.mIsStartGuestSession) {
- return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
- mContext.getResources(), UserHandle.USER_NULL, false));
+ return mUserManagerHelper.getGuestDefaultIcon();
}
if (userRecord.mIsAddUser) {
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 f6ec493..bba271b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -521,7 +521,7 @@
// Clear any pending suggestion flag as it has either been nullified or is being shown
mPendingRotationSuggestion = false;
- getView().removeCallbacks(mCancelPendingRotationProposal);
+ if (getView() != null) getView().removeCallbacks(mCancelPendingRotationProposal);
// Handle the visibility change and animation
if (visible) { // Appear and change (cannot force)
@@ -1141,6 +1141,7 @@
private final Runnable mRipple = new Runnable() {
@Override
public void run() { // Cause the ripple to fire via false presses
+ if (!mRoot.isAttachedToWindow()) return;
mRoot.setPressed(true);
mRoot.setPressed(false);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0038e89..bd59ec0 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2079,7 +2079,8 @@
}
getUiForShowing().showFillUi(filledId, response, filterText,
- mService.getServicePackageName(), mComponentName.getPackageName(), this);
+ mService.getServicePackageName(), mComponentName.getPackageName(),
+ mService.getServiceLabel(), mService.getServiceIcon(), this);
synchronized (mLock) {
if (mUiShownTime == 0) {
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 21a39e4..ee18dc2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -163,11 +163,14 @@
* @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 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 AutoFillUiCallback callback) {
+ @NonNull String packageName, @NonNull CharSequence serviceLabel,
+ @NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback) {
if (sDebug) {
final int size = filterText == null ? 0 : filterText.length();
Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
@@ -185,7 +188,7 @@
}
hideAllUiThread(callback);
mFillUi = new FillUi(mContext, response, focusedId,
- filterText, mOverlayControl, new FillUi.Callback() {
+ filterText, mOverlayControl, serviceLabel, serviceIcon, new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
log.setType(MetricsEvent.TYPE_DETAIL);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d29ca05..1aeb3b9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -26,6 +26,8 @@
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.ContextThemeWrapper;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
@@ -53,9 +55,11 @@
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.FrameLayout;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RemoteViews;
+import android.widget.TextView;
import com.android.internal.R;
import com.android.server.UiThread;
@@ -72,30 +76,10 @@
final class FillUi {
private static final String TAG = "FillUi";
+ private static final int THEME_ID = com.android.internal.R.style.Theme_DeviceDefault_Autofill;
+
private static final TypedValue sTempTypedValue = new TypedValue();
- public static final class AutofillFrameLayout extends FrameLayout {
-
- OnKeyListener mUnhandledListener;
-
- public AutofillFrameLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AutofillFrameLayout(Context context, AttributeSet attrs, @AttrRes int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- boolean handled = super.dispatchKeyEvent(event);
- if (!handled) {
- handled = mUnhandledListener.onKey(this, event.getKeyCode(), event);
- }
- return handled;
- }
- }
-
interface Callback {
void onResponsePicked(@NonNull FillResponse response);
void onDatasetPicked(@NonNull Dataset dataset);
@@ -146,51 +130,64 @@
FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
- @NonNull OverlayControl overlayControl, @NonNull Callback callback) {
- mContext = context;
+ @NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
+ @NonNull Drawable serviceIcon, @NonNull Callback callback) {
mCallback = callback;
mFullScreen = isFullScreen(context);
-
- final LayoutInflater inflater = LayoutInflater.from(context);
+ mContext = new ContextThemeWrapper(context, THEME_ID);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
final RemoteViews headerPresentation = response.getHeader();
final RemoteViews footerPresentation = response.getFooter();
final ViewGroup decor;
- if (headerPresentation != null || footerPresentation != null) {
- decor = (ViewGroup) inflater.inflate(
- mFullScreen ? R.layout.autofill_dataset_picker_header_footer_fullscreen
- : R.layout.autofill_dataset_picker_header_footer, null);
+ if (mFullScreen) {
+ decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
+ } else if (headerPresentation != null || footerPresentation != null) {
+ decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_header_footer,
+ null);
} else {
- decor = (ViewGroup) inflater.inflate(
- mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
- : R.layout.autofill_dataset_picker, null);
+ decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker, null);
+ }
+ final TextView titleView = decor.findViewById(R.id.autofill_dataset_title);
+ if (titleView != null) {
+ titleView.setText(mContext.getString(R.string.autofill_window_title, serviceLabel));
+ }
+ final ImageView iconView = decor.findViewById(R.id.autofill_dataset_icon);
+ if (iconView != null) {
+ iconView.setImageDrawable(serviceIcon);
}
- // if autofill ui is not fullscreen, send unhandled keyevent to app window.
- if (!mFullScreen) {
- if (decor instanceof AutofillFrameLayout) {
- ((AutofillFrameLayout) decor).mUnhandledListener =
- (View view, int keyCode, KeyEvent event) -> {
- switch (keyCode) {
- case KeyEvent.KEYCODE_BACK:
- case KeyEvent.KEYCODE_ESCAPE:
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return false;
- default:
- mCallback.dispatchUnhandledKey(event);
- return true;
- }
- };
- } else {
- Slog.wtf(TAG, "Unable to send unhandled key");
+ // In full screen we only initialize size once assuming screen size never changes
+ if (mFullScreen) {
+ final Point outPoint = mTempPoint;
+ mContext.getDisplay().getSize(outPoint);
+ // full with of screen and half height of screen
+ mContentWidth = LayoutParams.MATCH_PARENT;
+ mContentHeight = outPoint.y / 2;
+ if (sVerbose) {
+ Slog.v(TAG, "initialized fillscreen LayoutParams "
+ + mContentWidth + "," + mContentHeight);
}
}
+ // Send unhandled keyevent to app window.
+ decor.addOnUnhandledKeyEventListener((View view, KeyEvent event) -> {
+ switch (event.getKeyCode() ) {
+ case KeyEvent.KEYCODE_BACK:
+ case KeyEvent.KEYCODE_ESCAPE:
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ case KeyEvent.KEYCODE_DPAD_UP:
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ return false;
+ default:
+ mCallback.dispatchUnhandledKey(event);
+ return true;
+ }
+ });
+
if (sVisibleDatasetsMaxCount > 0) {
mVisibleDatasetsMaxCount = sVisibleDatasetsMaxCount;
if (sVerbose) {
@@ -218,14 +215,12 @@
mFooter = null;
mAdapter = null;
- // insert authentication item under autofill_dataset_container or decor
- ViewGroup container = decor.findViewById(R.id.autofill_dataset_container);
- if (container == null) {
- container = decor;
- }
+ // insert authentication item under autofill_dataset_picker
+ ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
final View content;
try {
- content = response.getPresentation().apply(context, decor, interceptionHandler);
+ response.getPresentation().setApplyTheme(THEME_ID);
+ content = response.getPresentation().apply(mContext, decor, interceptionHandler);
container.addView(content);
} catch (RuntimeException e) {
callback.onCanceled();
@@ -236,20 +231,22 @@
decor.setFocusable(true);
decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
- final Point maxSize = mTempPoint;
- resolveMaxWindowSize(context, maxSize);
- // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
- content.getLayoutParams().width = mFullScreen ? maxSize.x
- : ViewGroup.LayoutParams.WRAP_CONTENT;
- content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
- final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
- MeasureSpec.AT_MOST);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
- MeasureSpec.AT_MOST);
+ if (!mFullScreen) {
+ final Point maxSize = mTempPoint;
+ resolveMaxWindowSize(mContext, maxSize);
+ // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
+ content.getLayoutParams().width = mFullScreen ? maxSize.x
+ : ViewGroup.LayoutParams.WRAP_CONTENT;
+ content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
+ MeasureSpec.AT_MOST);
+ final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
+ MeasureSpec.AT_MOST);
- decor.measure(widthMeasureSpec, heightMeasureSpec);
- mContentWidth = content.getMeasuredWidth();
- mContentHeight = content.getMeasuredHeight();
+ decor.measure(widthMeasureSpec, heightMeasureSpec);
+ mContentWidth = content.getMeasuredWidth();
+ mContentHeight = content.getMeasuredHeight();
+ }
mWindow = new AnchoredWindow(decor, overlayControl);
requestShowFillUi();
@@ -263,7 +260,8 @@
RemoteViews.OnClickHandler clickBlocker = null;
if (headerPresentation != null) {
clickBlocker = newClickBlocker();
- mHeader = headerPresentation.apply(context, null, clickBlocker);
+ headerPresentation.setApplyTheme(THEME_ID);
+ mHeader = headerPresentation.apply(mContext, null, clickBlocker);
final LinearLayout headerContainer =
decor.findViewById(R.id.autofill_dataset_header);
if (sVerbose) Slog.v(TAG, "adding header");
@@ -274,15 +272,21 @@
}
if (footerPresentation != null) {
- if (clickBlocker == null) { // already set for header
- clickBlocker = newClickBlocker();
- }
- mFooter = footerPresentation.apply(context, null, clickBlocker);
final LinearLayout footerContainer =
decor.findViewById(R.id.autofill_dataset_footer);
- if (sVerbose) Slog.v(TAG, "adding footer");
- footerContainer.addView(mFooter);
- footerContainer.setVisibility(View.VISIBLE);
+ if (footerContainer != null) {
+ if (clickBlocker == null) { // already set for header
+ clickBlocker = newClickBlocker();
+ }
+ footerPresentation.setApplyTheme(THEME_ID);
+ mFooter = footerPresentation.apply(mContext, null, clickBlocker);
+ // Footer not supported on some platform e.g. TV
+ if (sVerbose) Slog.v(TAG, "adding footer");
+ footerContainer.addView(mFooter);
+ footerContainer.setVisibility(View.VISIBLE);
+ } else {
+ mFooter = null;
+ }
} else {
mFooter = null;
}
@@ -301,7 +305,8 @@
final View view;
try {
if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
- view = presentation.apply(context, null, interceptionHandler);
+ presentation.setApplyTheme(THEME_ID);
+ view = presentation.apply(mContext, null, interceptionHandler);
} catch (RuntimeException e) {
Slog.e(TAG, "Error inflating remote views", e);
continue;
@@ -352,12 +357,7 @@
}
void requestShowFillUi() {
- if (mFullScreen) {
- mCallback.requestShowFillUi(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- mWindowPresenter);
- } else {
- mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
- }
+ mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
}
/**
@@ -388,12 +388,6 @@
mCallback.requestHideFillUi();
} else {
if (updateContentSize()) {
- if (mFullScreen) {
- LayoutParams lp = mListView.getLayoutParams();
- lp.width = mContentWidth;
- lp.height = mContentHeight;
- mListView.setLayoutParams(lp);
- }
requestShowFillUi();
}
if (mAdapter.getCount() > mVisibleDatasetsMaxCount) {
@@ -452,6 +446,10 @@
if (mAdapter == null) {
return false;
}
+ if (mFullScreen) {
+ // always request show fill window with fixed size for fullscreen
+ return true;
+ }
boolean changed = false;
if (mAdapter.getCount() <= 0) {
if (mContentWidth != 0) {
@@ -476,11 +474,6 @@
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
MeasureSpec.AT_MOST);
final int itemCount = mAdapter.getCount();
- if (mFullScreen) {
- // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
- changed = true;
- mContentWidth = maxSize.x;
- }
if (mHeader != null) {
mHeader.measure(widthMeasureSpec, heightMeasureSpec);
@@ -491,20 +484,9 @@
for (int i = 0; i < itemCount; i++) {
final View view = mAdapter.getItem(i).view;
view.measure(widthMeasureSpec, heightMeasureSpec);
- if (mFullScreen) {
- // for fullscreen, add up all children height until hit max height.
- final int newContentHeight = mContentHeight + view.getMeasuredHeight();
- final int clampedNewHeight = Math.min(newContentHeight, maxSize.y);
- if (clampedNewHeight != mContentHeight) {
- mContentHeight = clampedNewHeight;
- } else if (view.getMeasuredHeight() > 0) {
- break;
- }
- } else {
- changed |= updateWidth(view, maxSize);
- if (i < mVisibleDatasetsMaxCount) {
- changed |= updateHeight(view, maxSize);
- }
+ changed |= updateWidth(view, maxSize);
+ if (i < mVisibleDatasetsMaxCount) {
+ changed |= updateHeight(view, maxSize);
}
}
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 f96fa7c2..80903c1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -42,6 +42,7 @@
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
+import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -70,6 +71,9 @@
private static final String TAG = "AutofillSaveUi";
+ private static final int THEME_ID =
+ com.android.internal.R.style.Theme_DeviceDefault_Autofill_Save;
+
public interface OnSaveListener {
void onSave();
void onCancel(IntentSender listener);
@@ -144,6 +148,7 @@
mServicePackageName = servicePackageName;
mPackageName = packageName;
+ context = new ContextThemeWrapper(context, THEME_ID);
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -222,7 +227,7 @@
final View yesButton = view.findViewById(R.id.autofill_save_yes);
yesButton.setOnClickListener((v) -> mListener.onSave());
- mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
+ mDialog = new Dialog(context, THEME_ID);
mDialog.setContentView(view);
// Dialog can be dismissed when touched outside, but the negative listener should not be
@@ -309,6 +314,7 @@
try {
// Create the remote view peer.
+ template.setApplyTheme(THEME_ID);
final View customSubtitleView = template.apply(context, null, handler);
// And apply batch updates (if any).
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index ae14dfa..1cd853f 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -56,7 +56,10 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (args != null) {
for (final String arg : args) {
- if ("--reset".equals(arg)) {
+ if ("-a".equals(arg)) {
+ // We currently dump all information by default
+ continue;
+ } else if ("--reset".equals(arg)) {
reset();
pw.println("binder_calls_stats reset.");
return;
@@ -78,7 +81,6 @@
return;
} else {
pw.println("Unknown option: " + arg);
- return;
}
}
}
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 676f0c7..1149e87 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -23,6 +23,7 @@
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
+import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
@@ -59,11 +60,14 @@
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
null);
- FileDescriptor fileDescriptor = UserManagerService.getInstance()
- .getUserIcon(mNewUser.id).getFileDescriptor();
- Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
- ((ImageView) view.findViewById(R.id.user_loading_avatar))
- .setImageBitmap(bitmap);
+ UserManager userManager =
+ (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
+ if (bitmap != null) {
+ ((ImageView) view.findViewById(R.id.user_loading_avatar))
+ .setImageBitmap(bitmap);
+ }
+
((TextView) view.findViewById(R.id.user_loading))
.setText(res.getString(R.string.car_loading_profile));
setView(view);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 550c37a..483fec6 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -219,6 +219,9 @@
}
public void unregisterCancelListenerLocked(IResultReceiver receiver) {
+ if (mCancelCallbacks == null) {
+ return; // Already unregistered or detached.
+ }
mCancelCallbacks.unregister(receiver);
if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
mCancelCallbacks = null;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 312b21c..03046b6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -818,37 +818,7 @@
}
};
- mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
- @Override
- public boolean isAvailableInPlatform() {
- return native_is_measurement_supported();
- }
-
- @Override
- protected int registerWithService() {
- int devOptions = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0);
- int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING , 0);
- boolean result = false;
- if (devOptions == 1 /* Developer Mode enabled */
- && fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */) {
- result = native_start_measurement_collection(true /* enableFullTracking */);
- } else {
- result = native_start_measurement_collection(false /* enableFullTracking */);
- }
- if (result) {
- return RemoteListenerHelper.RESULT_SUCCESS;
- } else {
- return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
- }
- }
-
- @Override
- protected void unregisterFromService() {
- native_stop_measurement_collection();
- }
-
+ mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) {
@Override
protected boolean isGpsEnabled() {
return isEnabled();
@@ -1032,7 +1002,7 @@
Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
}
}
-
+
private void handleRequestLocation(boolean independentFromGnss) {
if (isRequestLocationRateLimited()) {
if (DEBUG) {
@@ -2790,13 +2760,6 @@
private native void native_update_network_state(boolean connected, int type,
boolean roaming, boolean available, String extraInfo, String defaultAPN);
- // Gps Hal measurements support.
- private static native boolean native_is_measurement_supported();
-
- private native boolean native_start_measurement_collection(boolean enableFullTracking);
-
- private native boolean native_stop_measurement_collection();
-
// Gps Navigation message support.
private static native boolean native_is_navigation_message_supported();
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 477dae6..0add863 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -16,12 +16,16 @@
package com.android.server.location;
+import android.content.Context;
import android.location.GnssMeasurementsEvent;
import android.location.IGnssMeasurementsListener;
import android.os.Handler;
import android.os.RemoteException;
+import android.provider.Settings;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* An base implementation for GPS measurements provider.
* It abstracts out the responsibility of handling listeners, while still allowing technology
@@ -29,22 +33,73 @@
*
* @hide
*/
-public abstract class GnssMeasurementsProvider
- extends RemoteListenerHelper<IGnssMeasurementsListener> {
+public abstract class GnssMeasurementsProvider extends
+ RemoteListenerHelper<IGnssMeasurementsListener> {
private static final String TAG = "GnssMeasurementsProvider";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- protected GnssMeasurementsProvider(Handler handler) {
+ private final Context mContext;
+ private final GnssMeasurementProviderNative mNative;
+
+ private boolean mIsCollectionStarted;
+ private boolean mEnableFullTracking;
+
+ protected GnssMeasurementsProvider(Context context, Handler handler) {
+ this(context, handler, new GnssMeasurementProviderNative());
+ }
+
+ @VisibleForTesting
+ GnssMeasurementsProvider(Context context, Handler handler,
+ GnssMeasurementProviderNative aNative) {
super(handler, TAG);
+ mContext = context;
+ mNative = aNative;
+ }
+
+ // TODO(b/37460011): Use this with death recovery logic.
+ void resumeIfStarted() {
+ if (DEBUG) {
+ Log.d(TAG, "resumeIfStarted");
+ }
+ if (mIsCollectionStarted) {
+ mNative.startMeasurementCollection(mEnableFullTracking);
+ }
+ }
+
+ @Override
+ public boolean isAvailableInPlatform() {
+ return mNative.isMeasurementSupported();
+ }
+
+ @Override
+ protected int registerWithService() {
+ int devOptions = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
+ int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0);
+ boolean enableFullTracking = (devOptions == 1 /* Developer Mode enabled */)
+ && (fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */);
+ boolean result = mNative.startMeasurementCollection(enableFullTracking);
+ if (result) {
+ mIsCollectionStarted = true;
+ mEnableFullTracking = enableFullTracking;
+ return RemoteListenerHelper.RESULT_SUCCESS;
+ } else {
+ return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
+ }
+ }
+
+ @Override
+ protected void unregisterFromService() {
+ boolean stopped = mNative.stopMeasurementCollection();
+ if (stopped) {
+ mIsCollectionStarted = false;
+ }
}
public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
ListenerOperation<IGnssMeasurementsListener> operation =
- new ListenerOperation<IGnssMeasurementsListener>() {
- @Override
- public void execute(IGnssMeasurementsListener listener) throws RemoteException {
- listener.onGnssMeasurementsReceived(event);
- }
- };
+ listener -> listener.onGnssMeasurementsReceived(event);
foreach(operation);
}
@@ -98,4 +153,25 @@
listener.onStatusChanged(mStatus);
}
}
+
+ @VisibleForTesting
+ static class GnssMeasurementProviderNative {
+ public boolean isMeasurementSupported() {
+ return native_is_measurement_supported();
+ }
+
+ public boolean startMeasurementCollection(boolean enableFullTracking) {
+ return native_start_measurement_collection(enableFullTracking);
+ }
+
+ public boolean stopMeasurementCollection() {
+ return native_stop_measurement_collection();
+ }
+ }
+
+ private static native boolean native_is_measurement_supported();
+
+ private static native boolean native_start_measurement_collection(boolean enableFullTracking);
+
+ private static native boolean native_stop_measurement_collection();
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2b4f34e..4d8718f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4227,6 +4227,11 @@
|| appId == Process.ROOT_UID) {
return false;
}
+ // Installer gets to see all static libs.
+ if (PackageManager.PERMISSION_GRANTED
+ == checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid)) {
+ return false;
+ }
}
// No package means no static lib as it is always on internal storage
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index a9cdafd..507f0a8 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -155,11 +155,10 @@
enforceAccess(pkg, uri);
int user = Binder.getCallingUserHandle().getIdentifier();
uri = maybeAddUserId(uri, user);
- getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token);
+ String slicePkg = getProviderPkg(uri, user);
+ getOrCreatePinnedSlice(uri, slicePkg).pin(pkg, specs, token);
- Uri finalUri = uri;
mHandler.post(() -> {
- String slicePkg = getProviderPkg(finalUri, user);
if (slicePkg != null && !Objects.equals(pkg, slicePkg)) {
mAppUsageStats.reportEvent(slicePkg, user,
isAssistant(pkg, user) || isDefaultHomeApp(pkg, user)
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index eab391e..19c5a3d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -922,6 +922,10 @@
* @return Whether this WindowContainer should be magnified by the accessibility magnifier.
*/
boolean shouldMagnify() {
+ if (mSurfaceControl == null) {
+ return false;
+ }
+
for (int i = 0; i < mChildren.size(); i++) {
if (!mChildren.get(i).shouldMagnify()) {
return false;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 3a9bbe4..b3b37d6 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1799,7 +1799,7 @@
return JNI_FALSE;
}
-static jboolean android_location_GnssLocationProvider_is_measurement_supported(
+static jboolean android_location_GnssMeasurementsProvider_is_measurement_supported(
JNIEnv* env, jclass clazz) {
if (gnssMeasurementIface != nullptr) {
return JNI_TRUE;
@@ -1808,7 +1808,7 @@
return JNI_FALSE;
}
-static jboolean android_location_GnssLocationProvider_start_measurement_collection(
+static jboolean android_location_GnssMeasurementsProvider_start_measurement_collection(
JNIEnv* /* env */,
jobject /* obj */,
jboolean enableFullTracking) {
@@ -1842,7 +1842,7 @@
return JNI_TRUE;
}
-static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
+static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection(
JNIEnv* env,
jobject obj) {
if (gnssMeasurementIface == nullptr) {
@@ -2178,18 +2178,6 @@
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
- {"native_is_measurement_supported",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_is_measurement_supported)},
- {"native_start_measurement_collection",
- "(Z)Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_start_measurement_collection)},
- {"native_stop_measurement_collection",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssLocationProvider_stop_measurement_collection)},
{"native_is_navigation_message_supported",
"()Z",
reinterpret_cast<void *>(
@@ -2269,6 +2257,22 @@
reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)},
};
+static const JNINativeMethod sMeasurementMethods[] = {
+ /* name, signature, funcPtr */
+ {"native_is_measurement_supported",
+ "()Z",
+ reinterpret_cast<void *>(
+ android_location_GnssMeasurementsProvider_is_measurement_supported)},
+ {"native_start_measurement_collection",
+ "(Z)Z",
+ reinterpret_cast<void *>(
+ android_location_GnssMeasurementsProvider_start_measurement_collection)},
+ {"native_stop_measurement_collection",
+ "()Z",
+ reinterpret_cast<void *>(
+ android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+};
+
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
jniRegisterNativeMethods(
env,
@@ -2280,6 +2284,11 @@
"com/android/server/location/GnssGeofenceProvider",
sGeofenceMethods,
NELEM(sGeofenceMethods));
+ jniRegisterNativeMethods(
+ env,
+ "com/android/server/location/GnssMeasurementsProvider",
+ sMeasurementMethods,
+ NELEM(sMeasurementMethods));
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",
diff --git a/services/net/java/android/net/dns/ResolvUtil.java b/services/net/java/android/net/dns/ResolvUtil.java
index 97d20f4..a2a6615 100644
--- a/services/net/java/android/net/dns/ResolvUtil.java
+++ b/services/net/java/android/net/dns/ResolvUtil.java
@@ -62,4 +62,13 @@
final long netidForResolv = NETID_USE_LOCAL_NAMESERVERS | (long) network.netId;
return new Network((int) netidForResolv);
}
+
+ public static Network makeNetworkWithPrivateDnsBypass(Network network) {
+ return new Network(network) {
+ @Override
+ public InetAddress[] getAllByName(String host) throws UnknownHostException {
+ return blockingResolveAllLocally(network, host);
+ }
+ };
+ }
}
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
new file mode 100644
index 0000000..23d6cf6
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
@@ -0,0 +1,90 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+/**
+ * Unit tests for {@link GnssMeasurementsProvider}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+ manifest = Config.NONE,
+ sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class GnssMeasurementsProviderTest {
+ @Mock
+ private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative;
+ private GnssMeasurementsProvider mTestProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mMockNative.startMeasurementCollection(anyBoolean())).thenReturn(true);
+ when(mMockNative.stopMeasurementCollection()).thenReturn(true);
+
+ mTestProvider = new GnssMeasurementsProvider(RuntimeEnvironment.application,
+ new Handler(Looper.myLooper()), mMockNative) {
+ @Override
+ public boolean isGpsEnabled() {
+ return true;
+ }
+ };
+ }
+
+ @Test
+ public void register_nativeStarted() {
+ mTestProvider.registerWithService();
+ verify(mMockNative).startMeasurementCollection(anyBoolean());
+ }
+
+ @Test
+ public void unregister_nativeStopped() {
+ mTestProvider.registerWithService();
+ mTestProvider.unregisterFromService();
+ verify(mMockNative).stopMeasurementCollection();
+ }
+
+ @Test
+ public void isSupported_nativeIsSupported() {
+ when(mMockNative.isMeasurementSupported()).thenReturn(true);
+ assertThat(mTestProvider.isAvailableInPlatform()).isTrue();
+
+ when(mMockNative.isMeasurementSupported()).thenReturn(false);
+ assertThat(mTestProvider.isAvailableInPlatform()).isFalse();
+ }
+
+ @Test
+ public void register_resume_started() {
+ mTestProvider.registerWithService();
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(2)).startMeasurementCollection(anyBoolean());
+ }
+
+ @Test
+ public void unregister_resume_notStarted() {
+ mTestProvider.registerWithService();
+ mTestProvider.unregisterFromService();
+ mTestProvider.resumeIfStarted();
+ verify(mMockNative, times(1)).startMeasurementCollection(anyBoolean());
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index d49ba3e..43a4e27 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -93,7 +93,7 @@
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
- verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), eq("pkg"));
+ verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), anyString());
}
@Test
@@ -126,4 +126,4 @@
verify(mContextSpy).checkPermission(eq("perm2"), eq(Process.myPid()), eq(Process.myUid()));
}
-}
\ No newline at end of file
+}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 920a605..97c5ac9 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -81,7 +81,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.provider.Settings;
+import android.provider.Settings.Global;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.KeyValueListParser;
@@ -1439,8 +1439,10 @@
boolean isAppIdleEnabled() {
final boolean buildFlag = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableAutoPowerModes);
- final boolean runtimeFlag = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.APP_STANDBY_ENABLED, 1) == 1;
+ final boolean runtimeFlag = Global.getInt(mContext.getContentResolver(),
+ Global.APP_STANDBY_ENABLED, 1) == 1
+ && Global.getInt(mContext.getContentResolver(),
+ Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 1) == 1;
return buildFlag && runtimeFlag;
}
@@ -1489,8 +1491,8 @@
}
String getAppIdleSettings() {
- return Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.APP_IDLE_CONSTANTS);
+ return Global.getString(mContext.getContentResolver(),
+ Global.APP_IDLE_CONSTANTS);
}
}
@@ -1610,7 +1612,7 @@
};
/**
- * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}.
+ * Observe settings changes for {@link Global#APP_IDLE_CONSTANTS}.
*/
private class SettingsObserver extends ContentObserver {
/**
@@ -1650,10 +1652,11 @@
}
void registerObserver() {
- mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.APP_IDLE_CONSTANTS), false, this);
- mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.APP_STANDBY_ENABLED), false, this);
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.registerContentObserver(Global.getUriFor(Global.APP_IDLE_CONSTANTS), false, this);
+ cr.registerContentObserver(Global.getUriFor(Global.APP_STANDBY_ENABLED), false, this);
+ cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED),
+ false, this);
}
@Override
@@ -1665,11 +1668,14 @@
void updateSettings() {
if (DEBUG) {
Slog.d(TAG,
- "appidle=" + Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.APP_STANDBY_ENABLED));
- Slog.d(TAG, "appidleconstants=" + Settings.Global.getString(
+ "appidle=" + Global.getString(mContext.getContentResolver(),
+ Global.APP_STANDBY_ENABLED));
+ Slog.d(TAG,
+ "adaptivebat=" + Global.getString(mContext.getContentResolver(),
+ Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED));
+ Slog.d(TAG, "appidleconstants=" + Global.getString(
mContext.getContentResolver(),
- Settings.Global.APP_IDLE_CONSTANTS));
+ Global.APP_IDLE_CONSTANTS));
}
// Check if app_idle_enabled has changed
setAppIdleEnabled(mInjector.isAppIdleEnabled());