Merge "Reduce spacing between notification icons" into pi-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 20f0ba8..3b4a0be 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -384,16 +384,16 @@
public final class StatsManager {
method public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
- method public boolean addConfiguration(long, byte[]);
- method public byte[] getData(long);
- method public byte[] getMetadata();
+ method public deprecated boolean addConfiguration(long, byte[]);
+ method public deprecated byte[] getData(long);
+ method public deprecated byte[] getMetadata();
method public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException;
method public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
method public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
- method public boolean removeConfiguration(long);
+ method public deprecated boolean removeConfiguration(long);
method public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
- method public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
- method public boolean setDataFetchOperation(long, android.app.PendingIntent);
+ method public deprecated boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
+ method public deprecated boolean setDataFetchOperation(long, android.app.PendingIntent);
method public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException;
field public static final java.lang.String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
field public static final java.lang.String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 78b94ca..d278b55 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -352,13 +352,13 @@
Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
Landroid/app/AppOpsManager$OpEntry;->getDuration()I
-Landroid/app/AppOpsManager$OpEntry;->getMode()I
-Landroid/app/AppOpsManager$OpEntry;->getLastAccessTime()J
Landroid/app/AppOpsManager$OpEntry;->getLastAccessBackgroundTime()J
Landroid/app/AppOpsManager$OpEntry;->getLastAccessForegroundTime()J
-Landroid/app/AppOpsManager$OpEntry;->getLastRejectTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastAccessTime()J
Landroid/app/AppOpsManager$OpEntry;->getLastRejectBackgroundTime()J
Landroid/app/AppOpsManager$OpEntry;->getLastRejectForegroundTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastRejectTime()J
+Landroid/app/AppOpsManager$OpEntry;->getMode()I
Landroid/app/AppOpsManager$OpEntry;->getRejectTime()J
Landroid/app/AppOpsManager$PackageOps;-><init>(Ljava/lang/String;ILjava/util/List;)V
Landroid/app/AppOpsManager$PackageOps;->CREATOR:Landroid/os/Parcelable$Creator;
@@ -1041,6 +1041,7 @@
Landroid/bluetooth/BluetoothA2dp;->setOptionalCodecsEnabled(Landroid/bluetooth/BluetoothDevice;I)V
Landroid/bluetooth/BluetoothA2dp;->stateToString(I)Ljava/lang/String;
Landroid/bluetooth/BluetoothA2dp;->supportsOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)I
+Landroid/bluetooth/BluetoothA2dpSink;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
Landroid/bluetooth/BluetoothAdapter;->factoryReset()Z
Landroid/bluetooth/BluetoothAdapter;->getBluetoothManager()Landroid/bluetooth/IBluetoothManager;
@@ -1116,6 +1117,7 @@
Landroid/bluetooth/BluetoothDevice;->EXTRA_SDP_SEARCH_STATUS:Ljava/lang/String;
Landroid/bluetooth/BluetoothDevice;->getAlias()Ljava/lang/String;
Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String;
+Landroid/bluetooth/BluetoothDevice;->getBatteryLevel()I
Landroid/bluetooth/BluetoothDevice;->getMessageAccessPermission()I
Landroid/bluetooth/BluetoothDevice;->getPhonebookAccessPermission()I
Landroid/bluetooth/BluetoothDevice;->getService()Landroid/bluetooth/IBluetooth;
@@ -1176,6 +1178,7 @@
Landroid/bluetooth/BluetoothHearingAid;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
Landroid/bluetooth/BluetoothHearingAid;->getActiveDevices()Ljava/util/List;
Landroid/bluetooth/BluetoothHearingAid;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
+Landroid/bluetooth/BluetoothMap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothMapClient;->sendMessage(Landroid/bluetooth/BluetoothDevice;[Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)Z
Landroid/bluetooth/BluetoothPan;-><init>(Landroid/content/Context;Landroid/bluetooth/BluetoothProfile$ServiceListener;)V
Landroid/bluetooth/BluetoothPan;->close()V
@@ -1187,11 +1190,13 @@
Landroid/bluetooth/BluetoothPan;->isValidDevice(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothPan;->log(Ljava/lang/String;)V
Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
+Landroid/bluetooth/BluetoothPbap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothProfile;->A2DP_SINK:I
Landroid/bluetooth/BluetoothProfile;->AVRCP_CONTROLLER:I
Landroid/bluetooth/BluetoothProfile;->PAN:I
Landroid/bluetooth/BluetoothProfile;->PRIORITY_AUTO_CONNECT:I
Landroid/bluetooth/BluetoothProfile;->PRIORITY_UNDEFINED:I
+Landroid/bluetooth/BluetoothSap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/BluetoothServerSocket;->mSocket:Landroid/bluetooth/BluetoothSocket;
Landroid/bluetooth/BluetoothSocket;->EADDRINUSE:I
Landroid/bluetooth/BluetoothSocket;->flush()V
@@ -1323,6 +1328,7 @@
Landroid/content/Context;->checkPermission(Ljava/lang/String;IILandroid/os/IBinder;)I
Landroid/content/Context;->COUNTRY_DETECTOR:Ljava/lang/String;
Landroid/content/Context;->createApplicationContext(Landroid/content/pm/ApplicationInfo;I)Landroid/content/Context;
+Landroid/content/Context;->ETHERNET_SERVICE:Ljava/lang/String;
Landroid/content/Context;->getBasePackageName()Ljava/lang/String;
Landroid/content/Context;->getDisplay()Landroid/view/Display;
Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
@@ -1401,6 +1407,7 @@
Landroid/content/ISyncAdapter$Stub;-><init>()V
Landroid/content/ISyncAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncAdapter;
Landroid/content/ISyncAdapter;->cancelSync(Landroid/content/ISyncContext;)V
+Landroid/content/ISyncAdapter;->onUnsyncableAccount(Landroid/content/ISyncAdapterUnsyncableAccountCallback;)V
Landroid/content/ISyncAdapter;->startSync(Landroid/content/ISyncContext;Ljava/lang/String;Landroid/accounts/Account;Landroid/os/Bundle;)V
Landroid/content/ISyncContext$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/ISyncContext$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1446,6 +1453,8 @@
Landroid/content/pm/ApplicationInfo;->secondaryCpuAbi:Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
Landroid/content/pm/ApplicationInfo;->versionCode:I
+Landroid/content/pm/BaseParceledListSlice;->getList()Ljava/util/List;
+Landroid/content/pm/BaseParceledListSlice;->writeParcelableCreator(Ljava/lang/Object;Landroid/os/Parcel;)V
Landroid/content/pm/ComponentInfo;->getComponentName()Landroid/content/ComponentName;
Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1719,6 +1728,8 @@
Landroid/content/pm/PackageStats;->userHandle:I
Landroid/content/pm/PackageUserState;-><init>()V
Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
+Landroid/content/pm/ParceledListSlice;->CREATOR:Landroid/os/Parcelable$ClassLoaderCreator;
+Landroid/content/pm/ParceledListSlice;->writeParcelableCreator(Landroid/os/Parcelable;Landroid/os/Parcel;)V
Landroid/content/pm/PermissionInfo;->protectionToString(I)Ljava/lang/String;
Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->componentName:Landroid/content/ComponentName;
Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->type:Ljava/lang/Object;
@@ -2212,6 +2223,7 @@
Landroid/graphics/drawable/VectorDrawable;->mTintFilter:Landroid/graphics/PorterDuffColorFilter;
Landroid/graphics/drawable/VectorDrawable;->setAllowCaching(Z)V
Landroid/graphics/FontFamily;-><init>()V
+Landroid/graphics/FontFamily;-><init>([Ljava/lang/String;I)V
Landroid/graphics/FontFamily;->abortCreation()V
Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
@@ -2298,6 +2310,7 @@
Landroid/graphics/TableMaskFilter;->CreateClipTable(II)Landroid/graphics/TableMaskFilter;
Landroid/graphics/TemporaryBuffer;->obtain(I)[C
Landroid/graphics/TemporaryBuffer;->recycle([C)V
+Landroid/graphics/Typeface;-><init>(J)V
Landroid/graphics/Typeface;->createFromFamilies([Landroid/graphics/FontFamily;)Landroid/graphics/Typeface;
Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;II)Landroid/graphics/Typeface;
Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
@@ -2307,6 +2320,7 @@
Landroid/graphics/Typeface;->native_instance:J
Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
+Landroid/graphics/Typeface;->sSystemFallbackMap:Ljava/util/Map;
Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
Landroid/graphics/Xfermode;->porterDuffMode:I
Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_GOOD:I
@@ -3259,6 +3273,14 @@
Landroid/net/ConnectivityManager;->TYPE_PROXY:I
Landroid/net/ConnectivityManager;->TYPE_WIFI_P2P:I
Landroid/net/ConnectivityManager;->unregisterNetworkFactory(Landroid/os/Messenger;)V
+Landroid/net/EthernetManager$Listener;->onAvailabilityChanged(Ljava/lang/String;Z)V
+Landroid/net/EthernetManager;->addListener(Landroid/net/EthernetManager$Listener;)V
+Landroid/net/EthernetManager;->getAvailableInterfaces()[Ljava/lang/String;
+Landroid/net/EthernetManager;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration;
+Landroid/net/EthernetManager;->isAvailable()Z
+Landroid/net/EthernetManager;->isAvailable(Ljava/lang/String;)Z
+Landroid/net/EthernetManager;->removeListener(Landroid/net/EthernetManager$Listener;)V
+Landroid/net/EthernetManager;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V
Landroid/net/http/SslCertificate;->getDigest(Ljava/security/cert/X509Certificate;Ljava/lang/String;)Ljava/lang/String;
Landroid/net/http/SslCertificate;->getSerialNumber(Ljava/security/cert/X509Certificate;)Ljava/lang/String;
Landroid/net/http/SslCertificate;->inflateCertificateView(Landroid/content/Context;)Landroid/view/View;
@@ -4148,6 +4170,7 @@
Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List;
Landroid/os/storage/StorageManager;->getVolumeState(Ljava/lang/String;)Ljava/lang/String;
Landroid/os/storage/StorageManager;->isFileEncryptedNativeOnly()Z
+Landroid/os/storage/StorageManager;->isUsbMassStorageConnected()Z
Landroid/os/storage/StorageManager;->isUsbMassStorageEnabled()Z
Landroid/os/storage/StorageManager;->partitionPublic(Ljava/lang/String;)V
Landroid/os/storage/StorageManager;->unmount(Ljava/lang/String;)V
@@ -4551,6 +4574,7 @@
Landroid/provider/Settings$System;->LOCKSCREEN_SOUNDS_ENABLED:Ljava/lang/String;
Landroid/provider/Settings$System;->LOCK_SOUND:Ljava/lang/String;
Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
+Landroid/provider/Settings$System;->NOTIFICATION_LIGHT_PULSE:Ljava/lang/String;
Landroid/provider/Settings$System;->POINTER_LOCATION:Ljava/lang/String;
Landroid/provider/Settings$System;->POINTER_SPEED:Ljava/lang/String;
Landroid/provider/Settings$System;->PRIVATE_SETTINGS:Ljava/util/Set;
@@ -5410,6 +5434,7 @@
Landroid/telephony/SubscriptionManager;->setDataRoaming(II)I
Landroid/telephony/SubscriptionManager;->setDefaultDataSubId(I)V
Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
+Landroid/telephony/SubscriptionManager;->setDisplayNumber(Ljava/lang/String;I)I
Landroid/telephony/TelephonyManager$MultiSimVariants;->TSTS:Landroid/telephony/TelephonyManager$MultiSimVariants;
Landroid/telephony/TelephonyManager$MultiSimVariants;->UNKNOWN:Landroid/telephony/TelephonyManager$MultiSimVariants;
Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 45754ae..32fc0dc 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -115,8 +115,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * TODO: Temporary for backwards compatibility. Remove.
+ * @deprecated Use {@link #addConfig(long, byte[])}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public boolean addConfiguration(long configKey, byte[] config) {
@@ -149,8 +150,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * TODO: Temporary for backwards compatibility. Remove.
+ * @deprecated Use {@link #removeConfig(long)}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public boolean removeConfiguration(long configKey) {
@@ -216,8 +218,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * TODO: Temporary for backwards compatibility. Remove.
+ * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public boolean setBroadcastSubscriber(
@@ -268,8 +271,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * TODO: Temporary for backwards compatibility. Remove.
+ * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
@@ -304,8 +308,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * TODO: Temporary for backwards compatibility. Remove.
+ * @deprecated Use {@link #getReports(long)}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public @Nullable byte[] getData(long configKey) {
@@ -339,12 +344,9 @@
}
}
+ // TODO: Temporary for backwards compatibility. Remove.
/**
- * Clients can request metadata for statsd. Will contain stats across all configurations but not
- * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}.
- * This getter is not destructive and will not reset any metrics/counters.
- *
- * @return Serialized StatsdStatsReport proto. Returns null on failure (eg, if statsd crashed).
+ * @deprecated Use {@link #getStatsMetadata()}
*/
@RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
public @Nullable byte[] getMetadata() {
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index f682ec1..ad862fc 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -245,7 +245,8 @@
ContentResolver resolver = mContext.getContentResolver();
try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
if (provider == null) {
- throw new IllegalArgumentException("Unknown URI " + uri);
+ Log.w(TAG, String.format("Unknown URI: %s", uri));
+ return null;
}
Bundle extras = new Bundle();
extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
@@ -306,7 +307,8 @@
.authority(authority).build();
try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
if (provider == null) {
- throw new IllegalArgumentException("Unknown URI " + uri);
+ Log.w(TAG, String.format("Unknown URI: %s", uri));
+ return null;
}
Bundle extras = new Bundle();
extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
@@ -383,7 +385,8 @@
.authority(authority).build();
try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
if (provider == null) {
- throw new IllegalArgumentException("Unknown URI " + uri);
+ Log.w(TAG, String.format("Unknown URI: %s", uri));
+ return null;
}
Bundle extras = new Bundle();
extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 2306e5f..16c1f6d 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -21,18 +21,15 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Paint.Align;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
-import android.graphics.Paint.Align;
-import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard.Key;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.GestureDetector;
@@ -662,11 +659,13 @@
invalidateAllKeys();
mKeyboardChanged = false;
}
- final Canvas canvas = mCanvas;
- canvas.clipRect(mDirtyRect, Op.REPLACE);
if (mKeyboard == null) return;
+ mCanvas.save();
+ final Canvas canvas = mCanvas;
+ canvas.clipRect(mDirtyRect);
+
final Paint paint = mPaint;
final Drawable keyBackground = mKeyBackground;
final Rect clipRegion = mClipRegion;
@@ -758,7 +757,7 @@
paint.setColor(0xFF00FF00);
canvas.drawCircle((mStartX + mLastX) / 2, (mStartY + mLastY) / 2, 2, paint);
}
-
+ mCanvas.restore();
mDrawPending = false;
mDirtyRect.setEmpty();
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 619ec23..221abed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -245,8 +245,10 @@
* New in version 31:
* - New cellular network types.
* - Deferred job metrics.
+ * New in version 32:
+ * - Ambient display properly output in data dump.
*/
- static final int CHECKIN_VERSION = 31;
+ static final int CHECKIN_VERSION = 32;
/**
* Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 576ea52..8d4c3c3 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -407,8 +407,12 @@
* {@link #TYPE_EMULATED} or {@link #TYPE_PUBLIC}.
*/
public @Nullable Intent buildBrowseIntent() {
+ return buildBrowseIntentForUser(UserHandle.myUserId());
+ }
+
+ public @Nullable Intent buildBrowseIntentForUser(int userId) {
final Uri uri;
- if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == UserHandle.myUserId()) {
+ if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == userId) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
} else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e9f7d2a..6f3a44e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -23,6 +23,7 @@
import static android.provider.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
import static android.provider.SettingsValidators.LOCALE_VALIDATOR;
import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
+import static android.provider.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR;
import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.SettingsValidators.URI_VALIDATOR;
@@ -5452,7 +5453,8 @@
@TestApi
public static final String AUTOFILL_SERVICE = "autofill_service";
- private static final Validator AUTOFILL_SERVICE_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+ private static final Validator AUTOFILL_SERVICE_VALIDATOR =
+ NULLABLE_COMPONENT_NAME_VALIDATOR;
/**
* Boolean indicating if Autofill supports field classification.
@@ -5950,7 +5952,7 @@
"accessibility_shortcut_target_service";
private static final Validator ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR =
- COMPONENT_NAME_VALIDATOR;
+ NULLABLE_COMPONENT_NAME_VALIDATOR;
/**
* Setting specifying the accessibility service or feature to be toggled via the
@@ -7112,6 +7114,35 @@
public static final String UI_NIGHT_MODE = "ui_night_mode";
/**
+ * The current device UI theme mode effect SystemUI and Launcher.<br/>
+ * <b>Values:</b><br/>
+ * 0 - The mode that theme will controlled by wallpaper color.<br/>
+ * 1 - The mode that will always light theme.<br/>
+ * 2 - The mode that will always dark theme.<br/>
+ *
+ * @hide
+ */
+ public static final String THEME_MODE = "theme_mode";
+
+ /**
+ * THEME_MODE value for wallpaper mode.
+ * @hide
+ */
+ public static final int THEME_MODE_WALLPAPER = 0;
+
+ /**
+ * THEME_MODE value for light theme mode.
+ * @hide
+ */
+ public static final int THEME_MODE_LIGHT = 1;
+
+ /**
+ * THEME_MODE value for dark theme mode.
+ * @hide
+ */
+ public static final int THEME_MODE_DARK = 2;
+
+ /**
* Whether screensavers are enabled.
* @hide
*/
@@ -11564,6 +11595,13 @@
/** @hide */ public static final int EMULATE_DISPLAY_CUTOUT_ON = 1;
/**
+ * A colon separated list of keys for Settings Slices.
+ *
+ * @hide
+ */
+ public static final String BLOCKED_SLICES = "blocked_slices";
+
+ /**
* Defines global zen mode. ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
* or ZEN_MODE_NO_INTERRUPTIONS.
*
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
index b53b0f0..25e77867 100644
--- a/core/java/android/provider/SettingsValidators.java
+++ b/core/java/android/provider/SettingsValidators.java
@@ -77,6 +77,11 @@
}
};
+ /**
+ * Does not allow a setting to have a null {@link ComponentName}. Use {@link
+ * SettingsValidators#NULLABLE_COMPONENT_NAME_VALIDATOR} instead if a setting can have a
+ * nullable {@link ComponentName}.
+ */
public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {
@@ -84,6 +89,16 @@
}
};
+ /**
+ * Allows a setting to have a null {@link ComponentName}.
+ */
+ public static final Validator NULLABLE_COMPONENT_NAME_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(@Nullable String value) {
+ return value == null || COMPONENT_NAME_VALIDATOR.validate(value);
+ }
+ };
+
public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 537065d..1d5c6f1 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -36,6 +36,10 @@
/**
* Proceed with the SSL certificate.
+ * <p>
+ * It is not recommended to proceed past SSL errors and this method should
+ * generally not be used; see {@link WebViewClient#onReceivedSslError} for
+ * more information.
*/
public void proceed() {}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4aa1c4a..95fe963 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -113,6 +113,20 @@
* the new WebView as an argument. If the host application chooses not to
* honor the request, it should return {@code false} from this method. The default
* implementation of this method does nothing and hence returns {@code false}.
+ * <p>
+ * Applications should typically not allow windows to be created when the
+ * {@code isUserGesture} flag is false, as this may be an unwanted popup.
+ * <p>
+ * Applications should be careful how they display the new window: don't simply
+ * overlay it over the existing WebView as this may mislead the user about which
+ * site they are viewing. If your application displays the URL of the main page,
+ * make sure to also display the URL of the new window in a similar fashion. If
+ * your application does not display URLs, consider disallowing the creation of
+ * new windows entirely.
+ * <p class="note"><b>Note:</b> There is no trustworthy way to tell which page
+ * requested the new window: the request might originate from a third-party iframe
+ * inside the WebView.
+ *
* @param view The WebView from which the request for a new window
* originated.
* @param isDialog {@code true} if the new window should be a dialog, rather than
@@ -149,6 +163,11 @@
* from the view system if necessary. At this point, WebCore has stopped
* any loading in this window and has removed any cross-scripting ability
* in javascript.
+ * <p>
+ * As with {@link #onCreateWindow}, the application should ensure that any
+ * URL or security indicator displayed is updated so that the user can tell
+ * that the page they were interacting with has been closed.
+ *
* @param window The WebView that needs to be closed.
*/
public void onCloseWindow(WebView window) {}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 10748ac..d7f1d6e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1019,11 +1019,21 @@
* If {@code null}, defaults to 'text/html'.
* <p>
* The 'data' scheme URL formed by this method uses the default US-ASCII
- * charset. If you need need to set a different charset, you should form a
+ * charset. If you need to set a different charset, you should form a
* 'data' scheme URL which explicitly specifies a charset parameter in the
* mediatype portion of the URL and call {@link #loadUrl(String)} instead.
* Note that the charset obtained from the mediatype portion of a data URL
* always overrides that specified in the HTML or XML document itself.
+ * <p>
+ * Content loaded using this method will have a {@code window.origin} value
+ * of {@code "null"}. This must not be considered to be a trusted origin
+ * by the application or by any JavaScript code running inside the WebView
+ * (for example, event sources in DOM event handlers or web messages),
+ * because malicious content can also create frames with a null origin. If
+ * you need to identify the main frame's origin in a trustworthy way, you
+ * should use {@link #loadDataWithBaseURL(String,String,String,String,String)
+ * loadDataWithBaseURL()} with a valid HTTP or HTTPS base URL to set the
+ * origin.
*
* @param data a String of data in the given encoding
* @param mimeType the MIME type of the data, e.g. 'text/html'.
@@ -1057,6 +1067,15 @@
* <p>
* Note that the baseUrl is sent in the 'Referer' HTTP header when
* requesting subresources (images, etc.) of the page loaded using this method.
+ * <p>
+ * If a valid HTTP or HTTPS base URL is not specified in {@code baseUrl}, then
+ * content loaded using this method will have a {@code window.origin} value
+ * of {@code "null"}. This must not be considered to be a trusted origin
+ * by the application or by any JavaScript code running inside the WebView
+ * (for example, event sources in DOM event handlers or web messages),
+ * because malicious content can also create frames with a null origin. If
+ * you need to identify the main frame's origin in a trustworthy way, you
+ * should use a valid HTTP or HTTPS base URL to set the origin.
*
* @param baseUrl the URL to use as the page's base URL. If {@code null} defaults to
* 'about:blank'.
@@ -2056,6 +2075,13 @@
* <p>
* A target origin can be set as a wildcard ("*"). However this is not recommended.
* See the page above for security issues.
+ * <p>
+ * Content loaded via {@link #loadData(String,String,String)} will not have a
+ * valid origin, and thus cannot be sent messages securely. If you need to send
+ * messages using this function, you should use
+ * {@link #loadDataWithBaseURL(String,String,String,String,String)} with a valid
+ * HTTP or HTTPS {@code baseUrl} to define a valid origin that can be used for
+ * messaging.
*
* @param message the WebMessage
* @param targetOrigin the target origin.
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 6df1655..f686b66 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -368,6 +368,15 @@
* handler.proceed(). Note that the decision may be retained for use in
* response to future SSL errors. The default behavior is to cancel the
* load.
+ * <p>
+ * Applications are advised not to prompt the user about SSL errors, as
+ * the user is unlikely to be able to make an informed security decision
+ * and WebView does not provide any UI for showing the details of the
+ * error in a meaningful way.
+ * <p>
+ * Application overrides of this method may display custom error pages or
+ * silently log issues, but it is strongly recommended to always call
+ * handler.cancel() and never allow proceeding past errors.
*
* @param view The WebView that is initiating the callback.
* @param handler An SslErrorHandler object that will handle the user's
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 97043c7..571878d 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
@@ -1022,6 +1023,11 @@
@Override
public void onListRebuilt() {
+ // don't support direct share on low ram devices
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ return;
+ }
+
if (mServiceTargets != null) {
pruneServiceTargets();
}
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 7116f3a..d135040 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -207,6 +207,8 @@
mAvatarView.setTranslationY(0.0f);
mSenderName.setAlpha(1.0f);
mSenderName.setTranslationY(0.0f);
+ mIsolatedMessage = null;
+ mMessages = null;
sInstancePool.release(MessagingGroup.this);
}
};
@@ -267,6 +269,11 @@
@Override
public int getMeasuredType() {
+ if (mIsolatedMessage != null) {
+ // We only want to show one group if we have an inline image, so let's return shortened
+ // to avoid displaying the other ones.
+ return MEASURED_SHORTENED;
+ }
boolean hasNormal = false;
for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
View child = mMessageContainer.getChildAt(i);
@@ -292,9 +299,6 @@
}
}
}
- if (mMessageContainer.getChildCount() == 0 && mIsolatedMessage != null) {
- return mIsolatedMessage.getMeasuredType();
- }
return MEASURED_NORMAL;
}
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 9048f87..c7ea781 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -206,7 +206,17 @@
final boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
int childTop;
- int childLeft = centerAligned ? left + (right - left) / 2 - mTotalWidth / 2 : 0;
+ int childLeft;
+ if (centerAligned) {
+ childLeft = mPaddingLeft + left + (right - left) / 2 - mTotalWidth / 2;
+ } else {
+ childLeft = mPaddingLeft;
+ int absoluteGravity = Gravity.getAbsoluteGravity(Gravity.START, getLayoutDirection());
+ if (absoluteGravity == Gravity.RIGHT) {
+ childLeft += right - left - mTotalWidth;
+ }
+ }
+
// Where bottom of child should go
final int height = bottom - top;
@@ -216,18 +226,6 @@
final int count = getChildCount();
- final int layoutDirection = getLayoutDirection();
- switch (Gravity.getAbsoluteGravity(Gravity.START, layoutDirection)) {
- case Gravity.RIGHT:
- childLeft += mPaddingLeft + right - left - mTotalWidth;
- break;
-
- case Gravity.LEFT:
- default:
- childLeft += mPaddingLeft;
- break;
- }
-
int start = 0;
int dir = 1;
//In case of RTL, start drawing from the last child.
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 5b7fc6e..5126794 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -132,6 +132,7 @@
Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
Settings.Global.BLE_SCAN_BACKGROUND_MODE,
+ Settings.Global.BLOCKED_SLICES,
Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT,
Settings.Global.BLOCKING_HELPER_STREAK_LIMIT,
Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
@@ -591,6 +592,7 @@
Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
Settings.Secure.SMS_DEFAULT_APPLICATION,
+ Settings.Secure.THEME_MODE,
Settings.Secure.TRUST_AGENTS_INITIALIZED,
Settings.Secure.TV_INPUT_CUSTOM_LABELS,
Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index 50f24d3..8909293 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -88,6 +88,23 @@
}
@Test
+ public void testNullableComponentNameValidator_onValidComponentName_returnsTrue() {
+ assertTrue(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(
+ "android/com.android.internal.backup.LocalTransport"));
+ }
+
+ @Test
+ public void testNullableComponentNameValidator_onInvalidComponentName_returnsFalse() {
+ assertFalse(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(
+ "rectangle"));
+ }
+
+ @Test
+ public void testNullableComponentNameValidator_onNullValue_returnsTrue() {
+ assertTrue(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(null));
+ }
+
+ @Test
public void testLocaleValidator() {
assertTrue(SettingsValidators.LOCALE_VALIDATOR.validate("en_US"));
assertTrue(SettingsValidators.LOCALE_VALIDATOR.validate("es"));
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 007cddd..b644cc3 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -458,7 +458,7 @@
// The chunk must be at least the size of the string pool header.
if (size < sizeof(ResStringPool_header)) {
- LOG_ALWAYS_FATAL("Bad string block: data size %zu is too small to be a string block", size);
+ ALOGW("Bad string block: data size %zu is too small to be a string block", size);
return (mError=BAD_TYPE);
}
@@ -468,7 +468,7 @@
if (validate_chunk(reinterpret_cast<const ResChunk_header*>(data), sizeof(ResStringPool_header),
reinterpret_cast<const uint8_t*>(data) + size,
"ResStringPool_header") != NO_ERROR) {
- LOG_ALWAYS_FATAL("Bad string block: malformed block dimensions");
+ ALOGW("Bad string block: malformed block dimensions");
return (mError=BAD_TYPE);
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 9828275..a768dd3 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -207,8 +207,9 @@
* after {@link Image#close Image.close()} has been called.
* </p>
* @return the HardwareBuffer associated with this Image or null if this Image doesn't support
- * this feature (e.g. {@link android.media.ImageWriter ImageWriter} or
- * {@link android.media.MediaCodec MediaCodec} don't).
+ * this feature. (Unsupported use cases include Image instances obtained through
+ * {@link android.media.MediaCodec MediaCodec}, and on versions prior to Android P,
+ * {@link android.media.ImageWriter ImageWriter}).
*/
@Nullable
public HardwareBuffer getHardwareBuffer() {
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 397768a..4c0153f 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -20,6 +20,7 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.HardwareBuffer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -58,12 +59,17 @@
* </p>
* <p>
* If the application already has an Image from {@link ImageReader}, the
- * application can directly queue this Image into ImageWriter (via
- * {@link #queueInputImage}), potentially with zero buffer copies. For the
- * {@link ImageFormat#PRIVATE PRIVATE} format Images produced by
- * {@link ImageReader}, this is the only way to send Image data to ImageWriter,
- * as the Image data aren't accessible by the application.
+ * application can directly queue this Image into the ImageWriter (via
+ * {@link #queueInputImage}), potentially with zero buffer copies. This
+ * even works if the image format of the ImageWriter is
+ * {@link ImageFormat#PRIVATE PRIVATE}, and prior to Android P is the only
+ * way to enqueue images into such an ImageWriter. Starting in Android P
+ * private images may also be accessed through their hardware buffers
+ * (when available) through the {@link Image#getHardwareBuffer()} method.
+ * Attempting to access the planes of a private image, will return an
+ * empty array.
* </p>
+ * <p>
* Once new input Images are queued into an ImageWriter, it's up to the
* downstream components (e.g. {@link ImageReader} or
* {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the
@@ -257,29 +263,26 @@
* <p>
* If the format of ImageWriter is {@link ImageFormat#PRIVATE PRIVATE} (
* {@link ImageWriter#getFormat()} == {@link ImageFormat#PRIVATE}), the
- * image buffer is inaccessible to the application, and calling this method
- * will result in an {@link IllegalStateException}. Instead, the application
- * should acquire images from some other component (e.g. an
+ * image buffer is accessible to the application only through the hardware
+ * buffer obtained through {@link Image#getHardwareBuffer()}. (On Android
+ * versions prior to P, dequeueing private buffers will cause an
+ * {@link IllegalStateException} to be thrown). Alternatively,
+ * the application can acquire images from some other component (e.g. an
* {@link ImageReader}), and queue them directly to this ImageWriter via the
* {@link ImageWriter#queueInputImage queueInputImage()} method.
* </p>
*
* @return The next available input Image from this ImageWriter.
* @throws IllegalStateException if {@code maxImages} Images are currently
- * dequeued, or the ImageWriter format is
- * {@link ImageFormat#PRIVATE PRIVATE}, or the input
- * {@link android.view.Surface Surface} has been abandoned by the
- * consumer component that provided the {@link android.view.Surface Surface}.
+ * dequeued, or the input {@link android.view.Surface Surface}
+ * has been abandoned by the consumer component that provided
+ * the {@link android.view.Surface Surface}. Prior to Android
+ * P, throws if the ImageWriter format is
+ * {@link ImageFormat#PRIVATE PRIVATE}.
* @see #queueInputImage
* @see Image#close
*/
public Image dequeueInputImage() {
- if (mWriterFormat == ImageFormat.PRIVATE) {
- throw new IllegalStateException(
- "PRIVATE format ImageWriter doesn't support this operation since the images are"
- + " inaccessible to the application!");
- }
-
if (mDequeuedImages.size() >= mMaxImages) {
throw new IllegalStateException("Already dequeued max number of Images " + mMaxImages);
}
@@ -743,6 +746,13 @@
}
@Override
+ public HardwareBuffer getHardwareBuffer() {
+ throwISEIfImageIsInvalid();
+
+ return nativeGetHardwareBuffer();
+ }
+
+ @Override
public Plane[] getPlanes() {
throwISEIfImageIsInvalid();
@@ -863,6 +873,8 @@
private synchronized native int nativeGetHeight();
private synchronized native int nativeGetFormat();
+
+ private synchronized native HardwareBuffer nativeGetHardwareBuffer();
}
// Native implemented ImageWriter methods.
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 392a1eb..ada91be 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2848,8 +2848,12 @@
mInbandTrackIndices.set(i);
}
+ if (tracks[i] == null) {
+ Log.w(TAG, "unexpected NULL track at index " + i);
+ }
// newly appeared inband track
- if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+ if (tracks[i] != null
+ && tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
SubtitleTrack track = mSubtitleController.addTrack(
tracks[i].getFormat());
mIndexTrackPairs.add(Pair.create(i, track));
diff --git a/media/java/android/media/audiofx/DynamicsProcessing.java b/media/java/android/media/audiofx/DynamicsProcessing.java
index 4c17ae1..1c3cff9 100644
--- a/media/java/android/media/audiofx/DynamicsProcessing.java
+++ b/media/java/android/media/audiofx/DynamicsProcessing.java
@@ -279,25 +279,24 @@
private static final boolean PREEQ_DEFAULT_ENABLED = true;
private static final boolean POSTEQ_DEFAULT_ENABLED = true;
-
private static final boolean MBC_DEFAULT_ENABLED = true;
- private static final float MBC_DEFAULT_ATTACK_TIME = 50; // ms
- private static final float MBC_DEFAULT_RELEASE_TIME = 120; // ms
- private static final float MBC_DEFAULT_RATIO = 2; // 1:N
- private static final float MBC_DEFAULT_THRESHOLD = -30; // dB
+ private static final float MBC_DEFAULT_ATTACK_TIME = 3; // ms
+ private static final float MBC_DEFAULT_RELEASE_TIME = 80; // ms
+ private static final float MBC_DEFAULT_RATIO = 1; // N:1
+ private static final float MBC_DEFAULT_THRESHOLD = -45; // dB
private static final float MBC_DEFAULT_KNEE_WIDTH = 0; // dB
- private static final float MBC_DEFAULT_NOISE_GATE_THRESHOLD = -80; // dB
- private static final float MBC_DEFAULT_EXPANDER_RATIO = 1.5f; // N:1
+ private static final float MBC_DEFAULT_NOISE_GATE_THRESHOLD = -90; // dB
+ private static final float MBC_DEFAULT_EXPANDER_RATIO = 1; // 1:N
private static final float MBC_DEFAULT_PRE_GAIN = 0; // dB
- private static final float MBC_DEFAULT_POST_GAIN = 10; // dB
+ private static final float MBC_DEFAULT_POST_GAIN = 0; // dB
private static final boolean LIMITER_DEFAULT_ENABLED = true;
private static final int LIMITER_DEFAULT_LINK_GROUP = 0;//;
- private static final float LIMITER_DEFAULT_ATTACK_TIME = 50; // ms
- private static final float LIMITER_DEFAULT_RELEASE_TIME = 120; // ms
- private static final float LIMITER_DEFAULT_RATIO = 2; // 1:N
- private static final float LIMITER_DEFAULT_THRESHOLD = -30; // dB
- private static final float LIMITER_DEFAULT_POST_GAIN = 10; // dB
+ private static final float LIMITER_DEFAULT_ATTACK_TIME = 1; // ms
+ private static final float LIMITER_DEFAULT_RELEASE_TIME = 60; // ms
+ private static final float LIMITER_DEFAULT_RATIO = 10; // N:1
+ private static final float LIMITER_DEFAULT_THRESHOLD = -2; // dB
+ private static final float LIMITER_DEFAULT_POST_GAIN = 0; // dB
private static final float DEFAULT_MIN_FREQUENCY = 220; // Hz
private static final float DEFAULT_MAX_FREQUENCY = 20000; // Hz
@@ -540,13 +539,14 @@
* band number, thus band 0 cutoffFrequency <= band 1 cutoffFrequency, and so on.
* @param attackTime Attack Time for compressor in milliseconds (ms)
* @param releaseTime Release Time for compressor in milliseconds (ms)
- * @param ratio Compressor ratio (1:N)
+ * @param ratio Compressor ratio (N:1) (input:output)
* @param threshold Compressor threshold measured in decibels (dB) from 0 dB Full Scale
* (dBFS).
* @param kneeWidth Width in decibels (dB) around compressor threshold point.
* @param noiseGateThreshold Noise gate threshold in decibels (dB) from 0 dB Full Scale
* (dBFS).
- * @param expanderRatio Expander ratio (N:1) for signals below the Noise Gate Threshold.
+ * @param expanderRatio Expander ratio (1:N) (input:output) for signals below the Noise Gate
+ * Threshold.
* @param preGain Gain applied to the signal BEFORE the compression.
* @param postGain Gain applied to the signal AFTER compression.
*/
@@ -618,13 +618,13 @@
*/
public void setReleaseTime(float releaseTime) { mReleaseTime = releaseTime; }
/**
- * gets the compressor ratio (1:N)
- * @return compressor ratio (1:N)
+ * gets the compressor ratio (N:1)
+ * @return compressor ratio (N:1)
*/
public float getRatio() { return mRatio; }
/**
- * sets compressor ratio (1:N)
- * @param ratio desired for the compressor (1:N)
+ * sets compressor ratio (N:1)
+ * @param ratio desired for the compressor (N:1)
*/
public void setRatio(float ratio) { mRatio = ratio; }
/**
@@ -670,13 +670,13 @@
public void setNoiseGateThreshold(float noiseGateThreshold) {
mNoiseGateThreshold = noiseGateThreshold; }
/**
- * gets Expander ratio (N:1) for signals below the Noise Gate Threshold.
- * @return Expander ratio (N:1)
+ * gets Expander ratio (1:N) for signals below the Noise Gate Threshold.
+ * @return Expander ratio (1:N)
*/
public float getExpanderRatio() { return mExpanderRatio; }
/**
- * sets Expander ratio (N:1) for signals below the Noise Gate Threshold.
- * @param expanderRatio desired expander ratio (N:1)
+ * sets Expander ratio (1:N) for signals below the Noise Gate Threshold.
+ * @param expanderRatio desired expander ratio (1:N)
*/
public void setExpanderRatio(float expanderRatio) { mExpanderRatio = expanderRatio; }
/**
@@ -909,7 +909,7 @@
* same linkGroup index will react together.
* @param attackTime Attack Time for limiter compressor in milliseconds (ms)
* @param releaseTime Release Time for limiter compressor in milliseconds (ms)
- * @param ratio Limiter Compressor ratio (1:N)
+ * @param ratio Limiter Compressor ratio (N:1) (input:output)
* @param threshold Limiter Compressor threshold measured in decibels (dB) from 0 dB Full
* Scale (dBFS).
* @param postGain Gain applied to the signal AFTER compression.
@@ -985,13 +985,13 @@
*/
public void setReleaseTime(float releaseTime) { mReleaseTime = releaseTime; }
/**
- * gets the limiter compressor ratio (1:N)
- * @return limiter compressor ratio (1:N)
+ * gets the limiter compressor ratio (N:1)
+ * @return limiter compressor ratio (N:1)
*/
public float getRatio() { return mRatio; }
/**
- * sets limiter compressor ratio (1:N)
- * @param ratio desired for the limiter compressor (1:N)
+ * sets limiter compressor ratio (N:1)
+ * @param ratio desired for the limiter compressor (N:1)
*/
public void setRatio(float ratio) { mRatio = ratio; }
/**
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 11659e4..f8f7a90 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -25,11 +25,14 @@
#include <gui/Surface.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <stdint.h>
#include <inttypes.h>
+#include <android/hardware_buffer_jni.h>
#define IMAGE_BUFFER_JNI_ID "mNativeBuffer"
#define IMAGE_FORMAT_UNKNOWN 0 // This is the same value as ImageFormat#UNKNOWN.
@@ -701,6 +704,20 @@
return static_cast<jint>(publicFmt);
}
+static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
+ GraphicBuffer* buffer;
+ Image_getNativeContext(env, thiz, &buffer, NULL);
+ if (buffer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Image is not initialized");
+ return NULL;
+ }
+ AHardwareBuffer* b = AHardwareBuffer_from_GraphicBuffer(buffer);
+ // don't user the public AHardwareBuffer_toHardwareBuffer() because this would force us
+ // to link against libandroid.so
+ return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, b);
+}
+
static void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) {
ALOGV("%s:", __FUNCTION__);
env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd));
@@ -818,10 +835,12 @@
static JNINativeMethod gImageMethods[] = {
{"nativeCreatePlanes", "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
- (void*)Image_createSurfacePlanes },
- {"nativeGetWidth", "()I", (void*)Image_getWidth },
- {"nativeGetHeight", "()I", (void*)Image_getHeight },
- {"nativeGetFormat", "()I", (void*)Image_getFormat },
+ (void*)Image_createSurfacePlanes },
+ {"nativeGetWidth", "()I", (void*)Image_getWidth },
+ {"nativeGetHeight", "()I", (void*)Image_getHeight },
+ {"nativeGetFormat", "()I", (void*)Image_getFormat },
+ {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
+ (void*)Image_getHardwareBuffer },
};
int register_android_media_ImageWriter(JNIEnv *env) {
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index d0973f0..b8353ee 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"সংযোগৰ ক্ষমতা অনুযায়ী সৰ্বোত্তম"</item>
<item msgid="364670732877872677">"উত্তম প্ৰচেষ্টা (অভিযোজিত বিট ৰেইট)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", সক্ৰিয়"</item>
+ <item msgid="8962366465966010158">", সক্ৰিয় (মিডিয়া)"</item>
+ <item msgid="4046665544396189228">", সক্ৰিয় (ফ\'ন)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"অফ কৰক"</item>
<item msgid="1593289376502312923">"৬৪কে."</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index e186bb4..6340034 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে"</item>
<item msgid="364670732877872677">"সেরা প্রচেষ্টা (অ্যাডাপ্টিভ বিট রেট)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", চালু আছে"</item>
+ <item msgid="8962366465966010158">", চালু আছে (মিডিয়া)"</item>
+ <item msgid="4046665544396189228">", চালু আছে (ফোন)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"বন্ধ আছে"</item>
<item msgid="1593289376502312923">"৬৪K"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 30a9339..ecf5525 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"કનેક્શનની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item>
<item msgid="364670732877872677">"ઉત્તમ પ્રયાસ (અનુકૂલનશીલ બિટ રેટ)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", સક્રિય"</item>
+ <item msgid="8962366465966010158">", સક્રિય (મીડિયા)"</item>
+ <item msgid="4046665544396189228">", સક્રિય (ફોન)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"બંધ"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 0e34b77..d1d0157 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -140,9 +140,9 @@
</string-array>
<string-array name="bluetooth_audio_active_device_summaries">
<item msgid="4862957058729193940"></item>
- <item msgid="6481691720774549651">"चालू है"</item>
- <item msgid="8962366465966010158">"चालू है (सिर्फ़ मीडिया के लिए)"</item>
- <item msgid="4046665544396189228">"चालू है (सिर्फ़ फ़ोन के लिए)"</item>
+ <item msgid="6481691720774549651">", चालू है"</item>
+ <item msgid="8962366465966010158">", चालू है (सिर्फ़ मीडिया के लिए)"</item>
+ <item msgid="4046665544396189228">", चालू है (सिर्फ़ फ़ोन के लिए)"</item>
</string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"बंद"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 3aef4ce..b073371 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"Fínstillt fyrir gæði tengingar"</item>
<item msgid="364670732877872677">"Bestu mögulegu gæði (breytilegur bitahraði)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", virkt"</item>
+ <item msgid="8962366465966010158">", virkt (hljóð- og myndefni)"</item>
+ <item msgid="4046665544396189228">", virkt (sími)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"Slökkt"</item>
<item msgid="1593289376502312923">"64 k"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 037c23f..8b6b8ca 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"אופטימיזציה להשגת איכות חיבור מרבית"</item>
<item msgid="364670732877872677">"האיכות הטובה ביותר (קצב העברת נתונים מותאם)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", פעיל"</item>
+ <item msgid="8962366465966010158">", פעיל (מדיה)"</item>
+ <item msgid="4046665544396189228">", פעיל (טלפון)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"כבוי"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index a66af95..75d5dcb 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"ಸಂಪರ್ಕ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
<item msgid="364670732877872677">"ಅತ್ಯುತ್ತಮ ಪ್ರಯತ್ನ (ಹೊಂದಿಸಬಹುದಾದ ಬಿಟ್ ಪ್ರಮಾಣ)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">"ಸಕ್ರಿಯ"</item>
+ <item msgid="8962366465966010158">", ಸಕ್ರಿಯ (ಮಾಧ್ಯಮ)"</item>
+ <item msgid="4046665544396189228">", ಸಕ್ರಿಯ (ಫೋನ್)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ಆಫ್"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 74689e3..3337913 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്തു"</item>
<item msgid="364670732877872677">"മികച്ച സംവിധാനം (അനുയോജ്യമായ ബിറ്റ് റേറ്റ്)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", സജീവം"</item>
+ <item msgid="8962366465966010158">", സജീവ (മീഡിയ)"</item>
+ <item msgid="4046665544396189228">", സജീവമായ (ഫോൺ)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ഓഫ്"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 841e564..f5bf2ea 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ केले"</item>
<item msgid="364670732877872677">"सर्वोत्तम प्रयत्न (अनुकूल बिट रेट)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", अॅक्टिव्ह"</item>
+ <item msgid="8962366465966010158">", अॅक्टिव्ह (मीडिया)"</item>
+ <item msgid="4046665544396189228">", अॅक्टिव्ह (फोन)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"बंद"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 95a26d2..4ed55cc 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको"</item>
<item msgid="364670732877872677">"उत्कृष्ट प्रयास (अनुकूलनीय बिट दर)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", सक्रिय"</item>
+ <item msgid="8962366465966010158">", सक्रिय (मिडिया)"</item>
+ <item msgid="4046665544396189228">", सक्रिय (फोन)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item>
<item msgid="1593289376502312923">"६४के"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 9da5d6e..18de8f9 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"ସଂଯୋଗର ଗୁଣବତ୍ତା ପାଇଁ ଅନୁକୂଳିତ"</item>
<item msgid="364670732877872677">"ସର୍ବୋତ୍ତମ ପ୍ରୟାସ (ଅନୁକୂଳ ବିଟ୍ ରେଟ୍)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", ସକ୍ରିୟ"</item>
+ <item msgid="8962366465966010158">", ସକ୍ରିୟ (ମିଡିଆ)"</item>
+ <item msgid="4046665544396189228">", ସକ୍ରିୟ (ଫୋନ୍)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ଅଫ୍"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 2b3b919..ddb40ce 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"కనెక్షన్ నాణ్యత కోసం అనుకూలీకరించబడింది"</item>
<item msgid="364670732877872677">"ఉత్తమ కృషి (అనుకూల బిట్ రేట్)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">", సక్రియంగా ఉంది"</item>
+ <item msgid="8962366465966010158">", (మీడియా) సక్రియంగా ఉంది"</item>
+ <item msgid="4046665544396189228">", (ఫోన్) సక్రియంగా ఉంది"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"ఆఫ్"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 6e2f904..c6eadd98 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -138,9 +138,12 @@
<item msgid="4681409244565426925">"کنکشن کے معیار کیلئے بہتر بنایا گيا"</item>
<item msgid="364670732877872677">"بہترین کوشش (اڈاپٹیو بٹ ریٹ)"</item>
</string-array>
- <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
- <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+ <string-array name="bluetooth_audio_active_device_summaries">
+ <item msgid="4862957058729193940"></item>
+ <item msgid="6481691720774549651">"، فعال"</item>
+ <item msgid="8962366465966010158">"، فعال (میڈیا)"</item>
+ <item msgid="4046665544396189228">"، فعال (فون)"</item>
+ </string-array>
<string-array name="select_logd_size_titles">
<item msgid="8665206199209698501">"آف"</item>
<item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 90140ff..f14d396 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -42,7 +42,7 @@
* hiding the wallpaper and changing the display mode is necessary to hide
* the black frame that's inherent to hardware specs.
*/
- public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2000;
+ public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 4500;
private final DozeMachine.Service mDozeService;
private final Handler mHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 2b7ab10..e52829a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -300,9 +300,11 @@
private void saveImportance() {
if (!mIsNonblockable) {
- // Only go through the lock screen/bouncer if the user didn't hit 'Keep showing'.
+ // Only go through the lock screen/bouncer if the user hit 'Stop notifications'.
+ // Otherwise, update the importance immediately.
if (mCheckSaveListener != null
- && !NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING.equals(mExitReason)) {
+ && NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS.equals(
+ mExitReason)) {
mCheckSaveListener.checkSave(this::updateImportance, mSbn);
} else {
updateImportance();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index d040f7c..ba265d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,13 +18,13 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.car.user.CarUserManagerHelper;
import android.content.Context;
import android.view.View;
import android.view.ViewStub;
import android.support.v7.widget.GridLayoutManager;
+import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -37,7 +37,7 @@
private final UserGridRecyclerView mUserGridView;
private final int mShortAnimDuration;
private final StatusBar mStatusBar;
- private final CarUserManagerHelper mCarUserManagerHelper;
+ private final UserManagerHelper mUserManagerHelper;
private int mCurrentForegroundUserId;
private boolean mShowing;
@@ -52,7 +52,7 @@
mUserGridView.buildAdapter();
mUserGridView.setUserSelectionListener(this::onUserSelected);
- mCarUserManagerHelper = new CarUserManagerHelper(context);
+ mUserManagerHelper = new UserManagerHelper(context);
updateCurrentForegroundUser();
mShortAnimDuration = mContainer.getResources()
@@ -84,11 +84,11 @@
}
private boolean foregroundUserChanged() {
- return mCurrentForegroundUserId != mCarUserManagerHelper.getCurrentForegroundUserId();
+ return mCurrentForegroundUserId != mUserManagerHelper.getForegroundUserId();
}
private void updateCurrentForegroundUser() {
- mCurrentForegroundUserId = mCarUserManagerHelper.getCurrentForegroundUserId();
+ mCurrentForegroundUserId = mUserManagerHelper.getForegroundUserId();
}
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
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 dda25ec..92dd060 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -21,7 +21,6 @@
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
-import android.car.user.CarUserManagerHelper;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.UserInfo;
@@ -42,6 +41,7 @@
import androidx.car.widget.PagedListView;
import com.android.internal.util.UserIcons;
+import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -53,16 +53,16 @@
* One of the uses of this is for the lock screen in auto.
*/
public class UserGridRecyclerView extends PagedListView implements
- CarUserManagerHelper.OnUsersUpdateListener {
+ UserManagerHelper.OnUsersUpdateListener {
private UserSelectionListener mUserSelectionListener;
private UserAdapter mAdapter;
- private CarUserManagerHelper mCarUserManagerHelper;
+ private UserManagerHelper mUserManagerHelper;
private Context mContext;
public UserGridRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
- mCarUserManagerHelper = new CarUserManagerHelper(mContext);
+ mUserManagerHelper = new UserManagerHelper(mContext);
}
/**
@@ -71,7 +71,7 @@
@Override
public void onFinishInflate() {
super.onFinishInflate();
- mCarUserManagerHelper.registerOnUsersUpdateListener(this);
+ mUserManagerHelper.registerOnUsersUpdateListener(this);
}
/**
@@ -80,7 +80,7 @@
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mCarUserManagerHelper.unregisterOnUsersUpdateListener();
+ mUserManagerHelper.unregisterOnUsersUpdateListener();
}
/**
@@ -89,8 +89,8 @@
* @return the adapter
*/
public void buildAdapter() {
- List<UserRecord> userRecords = createUserRecords(mCarUserManagerHelper
- .getAllUsers());
+ List<UserRecord> userRecords = createUserRecords(mUserManagerHelper
+ .getAllUsersExcludesSystemUser());
mAdapter = new UserAdapter(mContext, userRecords);
super.setAdapter(mAdapter);
}
@@ -103,19 +103,19 @@
continue;
}
boolean isForeground =
- mCarUserManagerHelper.getCurrentForegroundUserId() == userInfo.id;
+ mUserManagerHelper.getForegroundUserId() == userInfo.id;
UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
false /* isAddUser */, isForeground);
userRecords.add(record);
}
// Add guest user record if the foreground user is not a guest
- if (!mCarUserManagerHelper.isForegroundUserGuest()) {
+ if (!mUserManagerHelper.foregroundUserIsGuestUser()) {
userRecords.add(addGuestUserRecord());
}
// Add add user record if the foreground user can add users
- if (mCarUserManagerHelper.canForegroundUserAddUsers()) {
+ if (mUserManagerHelper.foregroundUserCanAddUsers()) {
userRecords.add(addUserRecord());
}
@@ -149,7 +149,7 @@
@Override
public void onUsersUpdate() {
mAdapter.clearUsers();
- mAdapter.updateUsers(createUserRecords(mCarUserManagerHelper.getAllUsers()));
+ mAdapter.updateUsers(createUserRecords(mUserManagerHelper.getAllUsersExcludesSystemUser()));
mAdapter.notifyDataSetChanged();
}
@@ -213,7 +213,7 @@
// If the user selects Guest, start the guest session.
if (userRecord.mIsStartGuestSession) {
- mCarUserManagerHelper.startNewGuestSession(mGuestName);
+ mUserManagerHelper.startNewGuestSession(mGuestName);
return;
}
@@ -240,14 +240,14 @@
return;
}
// If the user doesn't want to be a guest or add a user, switch to the user selected
- mCarUserManagerHelper.switchToUser(userRecord.mInfo);
+ mUserManagerHelper.switchToUser(userRecord.mInfo);
});
}
private Bitmap getUserRecordIcon(UserRecord userRecord) {
if (userRecord.mIsStartGuestSession) {
- return mCarUserManagerHelper.getGuestDefaultIcon();
+ return mUserManagerHelper.getGuestDefaultIcon();
}
if (userRecord.mIsAddUser) {
@@ -255,7 +255,7 @@
.getDrawable(R.drawable.car_add_circle_round));
}
- return mCarUserManagerHelper.getUserIcon(userRecord.mInfo);
+ return mUserManagerHelper.getUserIcon(userRecord.mInfo);
}
@Override
@@ -273,10 +273,7 @@
@Override
protected UserInfo doInBackground(String... userNames) {
- // Default to create a non admin user for now. Need to add logic
- // for user to choose whether they want to create an admin or non-admin
- // user later.
- return mCarUserManagerHelper.createNewNonAdminUser(userNames[0]);
+ return mUserManagerHelper.createNewUser(userNames[0]);
}
@Override
@@ -286,7 +283,7 @@
@Override
protected void onPostExecute(UserInfo user) {
if (user != null) {
- mCarUserManagerHelper.switchToUser(user);
+ mUserManagerHelper.switchToUser(user);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 1b658b8..93e9cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2090,7 +2090,8 @@
* @param animate should the change of the icons be animated.
*/
private void updateHideIconsForBouncer(boolean animate) {
- boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded && mStatusBarWindowHidden;
+ boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded
+ && (mStatusBarWindowHidden || mBouncerShowing);
boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing;
boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard;
if (mHideIconsForBouncer != shouldHideIconsForBouncer) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 91a4b07..db3f0d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -30,7 +30,6 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.util.ArrayList;
-import java.util.Collection;
/**
* A global state to track all input states for the algorithm.
@@ -72,6 +71,7 @@
private ExpandableNotificationRow mExpandingNotification;
private int mDarkTopPadding;
private float mDarkAmount;
+ private boolean mAppearing;
public AmbientState(Context context) {
reload(context);
@@ -436,4 +436,12 @@
public int getDarkTopPadding() {
return mDarkTopPadding;
}
+
+ public void setAppearing(boolean appearing) {
+ mAppearing = appearing;
+ }
+
+ public boolean isAppearing() {
+ return mAppearing;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index bd56d79..a2b33fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -885,7 +885,9 @@
float appearEndPosition = getAppearEndPosition();
float appearStartPosition = getAppearStartPosition();
float appearFraction = 1.0f;
- if (height >= appearEndPosition) {
+ boolean appearing = height < appearEndPosition;
+ mAmbientState.setAppearing(appearing);
+ if (!appearing) {
translationY = 0;
if (mShouldShowShelfOnly) {
stackHeight = mTopPadding + mShelf.getIntrinsicHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 85f33d7..0d50f5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -478,22 +478,6 @@
childState.hidden = false;
}
}
- // Let's hide all the views if we are not expanded. the views might otherwise be visible
- // in the headsup area if a view was swiped away
- if (!mIsExpanded) {
- for (int i = 0; i < childCount; i++) {
- boolean visible = false;
- View child = algorithmState.visibleChildren.get(i);
- if (child instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- visible = row.isHeadsUp() || row.isHeadsUpAnimatingAway();
- }
- if (!visible) {
- ExpandableViewState childState = resultState.getViewStateForView(child);
- childState.hidden = true;
- }
- }
- }
}
private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
@@ -536,6 +520,10 @@
int shelfStart = ambientState.getInnerHeight()
- ambientState.getShelf().getIntrinsicHeight();
+ if (ambientState.isAppearing() && !child.isAboveShelf()) {
+ // Don't show none heads-up notifications while in appearing phase.
+ childViewState.yTranslation = Math.max(childViewState.yTranslation, shelfStart);
+ }
childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
if (childViewState.yTranslation >= shelfStart) {
childViewState.hidden = !child.isExpandAnimationRunning() && !child.hasExpandingChild();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index d527465..2f8dfdc 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -640,7 +640,7 @@
}
private PendingIntent buildBrowsePendingIntent(VolumeInfo vol) {
- final Intent intent = vol.buildBrowseIntent();
+ final Intent intent = vol.buildBrowseIntentForUser(vol.getMountUserId());
final int requestKey = vol.getId().hashCode();
return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index d76b7f0..03474a8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -727,6 +727,12 @@
}
protected void onStateChangedH(State state) {
+ if (mState != null && state != null
+ && mState.ringerModeInternal != state.ringerModeInternal
+ && state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
+ mController.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK));
+ }
+
mState = state;
mDynamic.clear();
// add any new dynamic rows
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index bdeb8bc..a72fed4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -508,7 +508,6 @@
anyString(), eq(TEST_UID), eq(true));
}
-
@Test
public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
throws Exception {
@@ -537,6 +536,43 @@
anyString(), eq(TEST_UID), eq(true));
}
+ @Test
+ public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
+ throws Exception {
+ NotificationInfo.CheckSaveListener listener =
+ mock(NotificationInfo.CheckSaveListener.class);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+ 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+ null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+ false /* isNonblockable */, true /* isForBlockingHelper */,
+ true /* isUserSentimentNegative */);
+
+ mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+ mTestableLooper.processAllMessages();
+ verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
+ }
+
+ @Test
+ public void testCloseControls_checkSaveListenerDelaysStopNotifications()
+ throws Exception {
+ NotificationInfo.CheckSaveListener listener =
+ mock(NotificationInfo.CheckSaveListener.class);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+ 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+ null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+ false /* isNonblockable */, true /* isForBlockingHelper */,
+ true /* isUserSentimentNegative */);
+
+ mNotificationInfo.findViewById(R.id.block).performClick();
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+ mTestableLooper.processAllMessages();
+ verify(listener).checkSave(any(Runnable.class), eq(mSbn));
+ }
@Test
public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 9ff8e7d..bf9ccb8 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -453,6 +453,10 @@
// Number of times the firmware picked a SoftAp channel not satisfying user band preference.
optional int32 num_soft_ap_user_band_preference_unsatisfied = 116;
+
+ // Identifier for experimental scoring parameter settings.
+ optional string score_experiment_id = 117;
+
}
// Information that gets logged for every WiFi connection.
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 fa2a0d9..a5311b2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -53,7 +53,6 @@
import android.view.autofill.AutofillManager;
import android.widget.ImageView;
import android.widget.RemoteViews;
-import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.R;
@@ -208,7 +207,7 @@
mSubTitle = info.getDescription();
if (mSubTitle != null) {
writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
- final ScrollView subtitleContainer =
+ final ViewGroup subtitleContainer =
view.findViewById(R.id.autofill_save_custom_subtitle);
final TextView subtitleView = new TextView(context);
subtitleView.setText(mSubTitle);
@@ -361,7 +360,7 @@
}
// Finally, add the custom description to the save UI.
- final ScrollView subtitleContainer =
+ final ViewGroup subtitleContainer =
saveUiView.findViewById(R.id.autofill_save_custom_subtitle);
subtitleContainer.addView(customSubtitleView);
subtitleContainer.setVisibility(View.VISIBLE);
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 2869114..5a25f48 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.annotation.Nullable;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -47,10 +49,18 @@
import dalvik.system.VMRuntime;
import java.io.FileDescriptor;
+import java.io.Closeable;
+import java.io.InputStream;
+import java.io.DataInputStream;
import java.io.IOException;
+import java.io.EOFException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipException;
+import java.util.zip.ZipEntry;
+
/**
* <p>PinnerService pins important files for key processes in memory.</p>
* <p>Files to pin are specified in the config_defaultPinnerServiceFiles
@@ -60,16 +70,18 @@
public final class PinnerService extends SystemService {
private static final boolean DEBUG = false;
private static final String TAG = "PinnerService";
+ private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
+ private static final String PIN_META_FILENAME = "pinlist.meta";
+ private static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE);
private final Context mContext;
- private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>();
- private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>();
private final boolean mShouldPinCamera;
+ /* These lists protected by PinnerService monitor lock */
+ private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>();
+ private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>();
+
private BinderService mBinderService;
-
- private final long MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
-
private PinnerHandler mPinnerHandler = null;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -146,18 +158,18 @@
// Files to pin come from the overlay and can be specified per-device config
String[] filesToPin = mContext.getResources().getStringArray(
com.android.internal.R.array.config_defaultPinnerServiceFiles);
- synchronized(this) {
- // Continue trying to pin remaining files even if there is a failure
- for (int i = 0; i < filesToPin.length; i++){
- PinnedFile pf = pinFile(filesToPin[i], 0, 0, 0);
- if (pf != null) {
- mPinnedFiles.add(pf);
- if (DEBUG) {
- Slog.i(TAG, "Pinned file = " + pf.mFilename);
- }
- } else {
- Slog.e(TAG, "Failed to pin file = " + filesToPin[i]);
- }
+ // Continue trying to pin each file even if we fail to pin some of them
+ for (String fileToPin : filesToPin) {
+ PinnedFile pf = pinFile(fileToPin,
+ Integer.MAX_VALUE,
+ /*attemptPinIntrospection=*/false);
+ if (pf == null) {
+ Slog.e(TAG, "Failed to pin file = " + fileToPin);
+ continue;
+ }
+
+ synchronized (this) {
+ mPinnedFiles.add(pf);
}
}
}
@@ -166,44 +178,23 @@
* Handler for camera pinning message
*/
private void handlePinCamera(int userHandle) {
- if (mShouldPinCamera) {
- synchronized(this) {
- boolean success = pinCamera(userHandle);
- if (!success) {
- //this is not necessarily an error
- if (DEBUG) {
- Slog.v(TAG, "Failed to pin camera.");
- }
- }
+ if (!mShouldPinCamera) return;
+ if (!pinCamera(userHandle)) {
+ if (DEBUG) {
+ Slog.v(TAG, "Failed to pin camera.");
}
}
}
- /**
- * determine if the camera app is already pinned by comparing the
- * intent resolution to the pinned files list
- */
- private boolean alreadyPinned(int userHandle) {
- ApplicationInfo cameraInfo = getCameraInfo(userHandle);
- if (cameraInfo == null ) {
- return false;
- }
- for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
- if (mPinnedCameraFiles.get(i).mFilename.equals(cameraInfo.sourceDir)) {
- if (DEBUG) {
- Slog.v(TAG, "Camera is already pinned");
- }
- return true;
- }
- }
- return false;
- }
-
private void unpinCameraApp() {
- for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
- unpinFile(mPinnedCameraFiles.get(i));
+ ArrayList<PinnedFile> pinnedCameraFiles;
+ synchronized (this) {
+ pinnedCameraFiles = new ArrayList<>(mPinnedCameraFiles);
+ mPinnedCameraFiles.clear();
}
- mPinnedCameraFiles.clear();
+ for (PinnedFile pinnedFile : pinnedCameraFiles) {
+ pinnedFile.close();
+ }
}
private boolean isResolverActivity(ActivityInfo info) {
@@ -255,15 +246,19 @@
//pin APK
String camAPK = cameraInfo.sourceDir;
- PinnedFile pf = pinFile(camAPK, 0, 0, MAX_CAMERA_PIN_SIZE);
+ PinnedFile pf = pinFile(camAPK,
+ MAX_CAMERA_PIN_SIZE,
+ /*attemptPinIntrospection=*/true);
if (pf == null) {
Slog.e(TAG, "Failed to pin " + camAPK);
return false;
}
if (DEBUG) {
- Slog.i(TAG, "Pinned " + pf.mFilename);
+ Slog.i(TAG, "Pinned " + pf.fileName);
}
- mPinnedCameraFiles.add(pf);
+ synchronized (this) {
+ mPinnedCameraFiles.add(pf);
+ }
// determine the ABI from either ApplicationInfo or Build
String arch = "arm";
@@ -289,11 +284,13 @@
//not pinning the oat/odex is not a fatal error
for (String file : files) {
- pf = pinFile(file, 0, 0, MAX_CAMERA_PIN_SIZE);
+ pf = pinFile(file, MAX_CAMERA_PIN_SIZE, /*attemptPinIntrospection=*/false);
if (pf != null) {
- mPinnedCameraFiles.add(pf);
+ synchronized (this) {
+ mPinnedCameraFiles.add(pf);
+ }
if (DEBUG) {
- Slog.i(TAG, "Pinned " + pf.mFilename);
+ Slog.i(TAG, "Pinned " + pf.fileName);
}
}
}
@@ -302,70 +299,294 @@
}
- /** mlock length bytes of fileToPin in memory, starting at offset
- * length == 0 means pin from offset to end of file
- * maxSize == 0 means infinite
+ /** mlock length bytes of fileToPin in memory
+ *
+ * If attemptPinIntrospection is true, then treat the file to pin as a zip file and
+ * look for a "pinlist.meta" file in the archive root directory. The structure of this
+ * file is a PINLIST_META as described below:
+ *
+ * <pre>
+ * PINLIST_META: PIN_RANGE*
+ * PIN_RANGE: PIN_START PIN_LENGTH
+ * PIN_START: big endian i32: offset in bytes of pin region from file start
+ * PIN_LENGTH: big endian i32: length of pin region in bytes
+ * </pre>
+ *
+ * (We use big endian because that's what DataInputStream is hardcoded to use.)
+ *
+ * If attemptPinIntrospection is false, then we use a single implicit PIN_RANGE of (0,
+ * maxBytesToPin); that is, we attempt to pin the first maxBytesToPin bytes of the file.
+ *
+ * After we open a file, we march through the list of pin ranges and attempt to pin
+ * each one, stopping after we've pinned maxBytesToPin bytes. (We may truncate the last
+ * pinned range to fit.) In this way, by choosing to emit certain PIN_RANGE pairs
+ * before others, file generators can express pins in priority order, making most
+ * effective use of the pinned-page quota.
+ *
+ * N.B. Each PIN_RANGE is clamped to the actual bounds of the file; all inputs have a
+ * meaningful interpretation. Also, a range locking a single byte of a page locks the
+ * whole page. Any truncated PIN_RANGE at EOF is ignored. Overlapping pinned entries
+ * are legal, but each pin of a byte counts toward the pin quota regardless of whether
+ * that byte has already been pinned, so the generator of PINLIST_META ought to ensure
+ * that ranges are non-overlapping.
+ *
+ * @param fileToPin Path to file to pin
+ * @param maxBytesToPin Maximum number of bytes to pin
+ * @param attemptPinIntrospection If true, try to open file as a
+ * zip in order to extract the
+ * @return Pinned memory resource owner thing or null on error
*/
- private static PinnedFile pinFile(String fileToPin, long offset, long length, long maxSize) {
- FileDescriptor fd = new FileDescriptor();
+ private static PinnedFile pinFile(String fileToPin,
+ int maxBytesToPin,
+ boolean attemptPinIntrospection) {
+ ZipFile fileAsZip = null;
+ InputStream pinRangeStream = null;
try {
- fd = Os.open(fileToPin,
- OsConstants.O_RDONLY | OsConstants.O_CLOEXEC | OsConstants.O_NOFOLLOW,
- OsConstants.O_RDONLY);
-
- StructStat sb = Os.fstat(fd);
-
- if (offset + length > sb.st_size) {
- Os.close(fd);
- Slog.e(TAG, "Failed to pin file " + fileToPin +
- ", request extends beyond end of file. offset + length = "
- + (offset + length) + ", file length = " + sb.st_size);
- return null;
+ if (attemptPinIntrospection) {
+ fileAsZip = maybeOpenZip(fileToPin);
}
- if (length == 0) {
- length = sb.st_size - offset;
+ if (fileAsZip != null) {
+ pinRangeStream = maybeOpenPinMetaInZip(fileAsZip, fileToPin);
}
- if (maxSize > 0 && length > maxSize) {
- Slog.e(TAG, "Could not pin file " + fileToPin +
- ", size = " + length + ", maxSize = " + maxSize);
- Os.close(fd);
- return null;
- }
+ Slog.d(TAG, "pinRangeStream: " + pinRangeStream);
- long address = Os.mmap(0, length, OsConstants.PROT_READ,
- OsConstants.MAP_PRIVATE, fd, offset);
- Os.close(fd);
-
- Os.mlock(address, length);
-
- return new PinnedFile(address, length, fileToPin);
- } catch (ErrnoException e) {
- Slog.e(TAG, "Could not pin file " + fileToPin + " with error " + e.getMessage());
- if(fd.valid()) {
- try {
- Os.close(fd);
- }
- catch (ErrnoException eClose) {
- Slog.e(TAG, "Failed to close fd, error = " + eClose.getMessage());
- }
- }
- return null;
+ PinRangeSource pinRangeSource = (pinRangeStream != null)
+ ? new PinRangeSourceStream(pinRangeStream)
+ : new PinRangeSourceStatic(0, Integer.MAX_VALUE /* will be clipped */);
+ return pinFileRanges(fileToPin, maxBytesToPin, pinRangeSource);
+ } finally {
+ safeClose(pinRangeStream);
+ safeClose(fileAsZip); // Also closes any streams we've opened
}
}
- private static boolean unpinFile(PinnedFile pf) {
+ /**
+ * Attempt to open a file as a zip file. On any sort of corruption, log, swallow the
+ * error, and return null.
+ */
+ private static ZipFile maybeOpenZip(String fileName) {
+ ZipFile zip = null;
try {
- Os.munlock(pf.mAddress, pf.mLength);
- } catch (ErrnoException e) {
- Slog.e(TAG, "Failed to unpin file " + pf.mFilename + " with error " + e.getMessage());
- return false;
+ zip = new ZipFile(fileName);
+ } catch (IOException ex) {
+ Slog.w(TAG,
+ String.format(
+ "could not open \"%s\" as zip: pinning as blob",
+ fileName),
+ ex);
}
- if (DEBUG) {
- Slog.i(TAG, "Unpinned file " + pf.mFilename );
+ return zip;
+ }
+
+ /**
+ * Open a pin metadata file in the zip if one is present.
+ *
+ * @param zipFile Zip file to search
+ * @return Open input stream or null on any error
+ */
+ private static InputStream maybeOpenPinMetaInZip(ZipFile zipFile, String fileName) {
+ ZipEntry pinMetaEntry = zipFile.getEntry(PIN_META_FILENAME);
+ InputStream pinMetaStream = null;
+ if (pinMetaEntry != null) {
+ try {
+ pinMetaStream = zipFile.getInputStream(pinMetaEntry);
+ } catch (IOException ex) {
+ Slog.w(TAG,
+ String.format("error reading pin metadata \"%s\": pinning as blob",
+ fileName),
+ ex);
+ }
}
- return true;
+ return pinMetaStream;
+ }
+
+ private static abstract class PinRangeSource {
+ /** Retrive a range to pin.
+ *
+ * @param outPinRange Receives the pin region
+ * @return True if we filled in outPinRange or false if we're out of pin entries
+ */
+ abstract boolean read(PinRange outPinRange);
+ }
+
+ private static final class PinRangeSourceStatic extends PinRangeSource {
+ private final int mPinStart;
+ private final int mPinLength;
+ private boolean mDone = false;
+
+ PinRangeSourceStatic(int pinStart, int pinLength) {
+ mPinStart = pinStart;
+ mPinLength = pinLength;
+ }
+
+ @Override
+ boolean read(PinRange outPinRange) {
+ outPinRange.start = mPinStart;
+ outPinRange.length = mPinLength;
+ boolean done = mDone;
+ mDone = true;
+ return !done;
+ }
+ }
+
+ private static final class PinRangeSourceStream extends PinRangeSource {
+ private final DataInputStream mStream;
+ private boolean mDone = false;
+
+ PinRangeSourceStream(InputStream stream) {
+ mStream = new DataInputStream(stream);
+ }
+
+ @Override
+ boolean read(PinRange outPinRange) {
+ if (!mDone) {
+ try {
+ outPinRange.start = mStream.readInt();
+ outPinRange.length = mStream.readInt();
+ } catch (IOException ex) {
+ mDone = true;
+ }
+ }
+ return !mDone;
+ }
+ }
+
+ /**
+ * Helper for pinFile.
+ *
+ * @param fileToPin Name of file to pin
+ * @param maxBytesToPin Maximum number of bytes to pin
+ * @param pinRangeSource Read PIN_RANGE entries from this stream to tell us what bytes
+ * to pin.
+ * @return PinnedFile or null on error
+ */
+ private static PinnedFile pinFileRanges(
+ String fileToPin,
+ int maxBytesToPin,
+ PinRangeSource pinRangeSource)
+ {
+ FileDescriptor fd = new FileDescriptor();
+ long address = -1;
+ int mapSize = 0;
+
+ try {
+ int openFlags = (OsConstants.O_RDONLY |
+ OsConstants.O_CLOEXEC |
+ OsConstants.O_NOFOLLOW);
+ fd = Os.open(fileToPin, openFlags, 0);
+ mapSize = (int) Math.min(Os.fstat(fd).st_size, Integer.MAX_VALUE);
+ address = Os.mmap(0, mapSize,
+ OsConstants.PROT_READ,
+ OsConstants.MAP_SHARED,
+ fd, /*offset=*/0);
+
+ PinRange pinRange = new PinRange();
+ int bytesPinned = 0;
+
+ // We pin at page granularity, so make sure the limit is page-aligned
+ if (maxBytesToPin % PAGE_SIZE != 0) {
+ maxBytesToPin -= maxBytesToPin % PAGE_SIZE;
+ }
+
+ while (bytesPinned < maxBytesToPin && pinRangeSource.read(pinRange)) {
+ int pinStart = pinRange.start;
+ int pinLength = pinRange.length;
+ pinStart = clamp(0, pinStart, mapSize);
+ pinLength = clamp(0, pinLength, mapSize - pinStart);
+ pinLength = Math.min(maxBytesToPin - bytesPinned, pinLength);
+
+ // mlock doesn't require the region to be page-aligned, but we snap the
+ // lock region to page boundaries anyway so that we don't under-count
+ // locking a single byte of a page as a charge of one byte even though the
+ // OS will retain the whole page. Thanks to this adjustment, we slightly
+ // over-count the pin charge of back-to-back pins touching the same page,
+ // but better that than undercounting. Besides: nothing stops pin metafile
+ // creators from making the actual regions page-aligned.
+ pinLength += pinStart % PAGE_SIZE;
+ pinStart -= pinStart % PAGE_SIZE;
+ if (pinLength % PAGE_SIZE != 0) {
+ pinLength += PAGE_SIZE - pinLength % PAGE_SIZE;
+ }
+ pinLength = clamp(0, pinLength, maxBytesToPin - bytesPinned);
+
+ if (pinLength > 0) {
+ if (DEBUG) {
+ Slog.d(TAG,
+ String.format(
+ "pinning at %s %s bytes of %s",
+ pinStart, pinLength, fileToPin));
+ }
+ Os.mlock(address + pinStart, pinLength);
+ }
+ bytesPinned += pinLength;
+ }
+
+ PinnedFile pinnedFile = new PinnedFile(address, mapSize, fileToPin, bytesPinned);
+ address = -1; // Ownership transferred
+ return pinnedFile;
+ } catch (ErrnoException ex) {
+ Slog.e(TAG, "Could not pin file " + fileToPin, ex);
+ return null;
+ } finally {
+ safeClose(fd);
+ if (address >= 0) {
+ safeMunmap(address, mapSize);
+ }
+ }
+ }
+
+ private static int clamp(int min, int value, int max) {
+ return Math.max(min, Math.min(value, max));
+ }
+
+ private static void safeMunmap(long address, long mapSize) {
+ try {
+ Os.munmap(address, mapSize);
+ } catch (ErrnoException ex) {
+ Slog.w(TAG, "ignoring error in unmap", ex);
+ }
+ }
+
+ /**
+ * Close FD, swallowing irrelevant errors.
+ */
+ private static void safeClose(@Nullable FileDescriptor fd) {
+ if (fd != null && fd.valid()) {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException ex) {
+ // Swallow the exception: non-EBADF errors in close(2)
+ // indicate deferred paging write errors, which we
+ // don't care about here. The underlying file
+ // descriptor is always closed.
+ if (ex.errno == OsConstants.EBADF) {
+ throw new AssertionError(ex);
+ }
+ }
+ }
+ }
+
+ /**
+ * Close closeable thing, swallowing errors.
+ */
+ private static void safeClose(@Nullable Closeable thing) {
+ if (thing != null) {
+ try {
+ thing.close();
+ } catch (IOException ex) {
+ Slog.w(TAG, "ignoring error closing resource: " + thing, ex);
+ }
+ }
+ }
+
+ private synchronized ArrayList<PinnedFile> snapshotPinnedFiles() {
+ int nrPinnedFiles = mPinnedFiles.size() + mPinnedCameraFiles.size();
+ ArrayList<PinnedFile> pinnedFiles = new ArrayList<>(nrPinnedFiles);
+ pinnedFiles.addAll(mPinnedFiles);
+ pinnedFiles.addAll(mPinnedCameraFiles);
+ return pinnedFiles;
}
private final class BinderService extends Binder {
@@ -373,31 +594,44 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
long totalSize = 0;
- pw.println("Pinned Files:");
- synchronized(this) {
- for (int i = 0; i < mPinnedFiles.size(); i++) {
- pw.println(mPinnedFiles.get(i).mFilename);
- totalSize += mPinnedFiles.get(i).mLength;
- }
- for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
- pw.println(mPinnedCameraFiles.get(i).mFilename);
- totalSize += mPinnedCameraFiles.get(i).mLength;
- }
+ for (PinnedFile pinnedFile : snapshotPinnedFiles()) {
+ pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned);
+ totalSize += pinnedFile.bytesPinned;
}
- pw.println("Total size: " + totalSize);
+ pw.format("Total size: %s\n", totalSize);
}
}
- private static class PinnedFile {
- long mAddress;
- long mLength;
- String mFilename;
+ private static final class PinnedFile implements AutoCloseable {
+ private long mAddress;
+ final int mapSize;
+ final String fileName;
+ final int bytesPinned;
- PinnedFile(long address, long length, String filename) {
+ PinnedFile(long address, int mapSize, String fileName, int bytesPinned) {
mAddress = address;
- mLength = length;
- mFilename = filename;
+ this.mapSize = mapSize;
+ this.fileName = fileName;
+ this.bytesPinned = bytesPinned;
}
+
+ @Override
+ public void close() {
+ if (mAddress >= 0) {
+ safeMunmap(mAddress, mapSize);
+ mAddress = -1;
+ }
+ }
+
+ @Override
+ public void finalize() {
+ close();
+ }
+ }
+
+ final static class PinRange {
+ int start;
+ int length;
}
final class PinnerHandler extends Handler {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 73710d3..d64b429 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1077,6 +1077,11 @@
// System process can launch home activity.
return true;
}
+ // Allow the recents component to launch the home activity.
+ final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
+ if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
+ return true;
+ }
// Resolver activity can launch home activity.
return sourceRecord != null && sourceRecord.isResolverActivity();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3c66526..99412c5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -489,6 +489,7 @@
mTemporaryScreenBrightness = -1;
mPendingScreenBrightnessSetting = -1;
mTemporaryAutoBrightnessAdjustment = Float.NaN;
+ mPendingAutoBrightnessAdjustment = Float.NaN;
}
/**
@@ -1499,6 +1500,7 @@
return false;
}
if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
+ mPendingAutoBrightnessAdjustment = Float.NaN;
return false;
}
mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 2621c50..c3b9841 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -55,6 +55,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.Xml.Encoding;
import com.android.internal.annotations.GuardedBy;
@@ -77,6 +78,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.function.Supplier;
public class SliceManagerService extends ISliceManager.Stub {
@@ -90,6 +92,10 @@
@GuardedBy("mLock")
private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>();
+ @GuardedBy("mLock")
+ private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>();
private final Handler mHandler;
private final SlicePermissionManager mPermissions;
@@ -453,17 +459,37 @@
}
private boolean isAssistant(String pkg, int userId) {
- final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId);
- if (cn == null) {
- return false;
- }
- return cn.getPackageName().equals(pkg);
+ return getAssistantMatcher(userId).matches(pkg);
}
private boolean isDefaultHomeApp(String pkg, int userId) {
- String defaultHome = getDefaultHome(userId);
+ return getHomeMatcher(userId).matches(pkg);
+ }
- return pkg != null && Objects.equals(pkg, defaultHome);
+ private PackageMatchingCache getAssistantMatcher(int userId) {
+ PackageMatchingCache matcher = mAssistantLookup.get(userId);
+ if (matcher == null) {
+ matcher = new PackageMatchingCache(() -> getAssistant(userId));
+ mAssistantLookup.put(userId, matcher);
+ }
+ return matcher;
+ }
+
+ private PackageMatchingCache getHomeMatcher(int userId) {
+ PackageMatchingCache matcher = mHomeLookup.get(userId);
+ if (matcher == null) {
+ matcher = new PackageMatchingCache(() -> getDefaultHome(userId));
+ mHomeLookup.put(userId, matcher);
+ }
+ return matcher;
+ }
+
+ private String getAssistant(int userId) {
+ final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId);
+ if (cn == null) {
+ return null;
+ }
+ return cn.getPackageName();
}
// Based on getDefaultHome in ShortcutService.
@@ -559,6 +585,30 @@
return mPermissions.getAllPackagesGranted(pkg);
}
+ /**
+ * Holder that caches a package that has access to a slice.
+ */
+ static class PackageMatchingCache {
+
+ private final Supplier<String> mPkgSource;
+ private String mCurrentPkg;
+
+ public PackageMatchingCache(Supplier<String> pkgSource) {
+ mPkgSource = pkgSource;
+ }
+
+ public boolean matches(String pkgCandidate) {
+ if (pkgCandidate == null) return false;
+
+ if (Objects.equals(pkgCandidate, mCurrentPkg)) {
+ return true;
+ }
+ // Failed on cached value, try updating.
+ mCurrentPkg = mPkgSource.get();
+ return Objects.equals(pkgCandidate, mCurrentPkg);
+ }
+ }
+
public static class Lifecycle extends SystemService {
private SliceManagerService mService;
diff --git a/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java b/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
index 3b6f9d6..8d53143 100644
--- a/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
@@ -29,7 +29,7 @@
"update_db");
public ApnDbInstallReceiver() {
- super("/data/misc/", "apns-conf.xml", "metadata/", "version");
+ super("/data/misc/apns/", "apns-conf.xml", "metadata/", "version");
}
@Override
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index a7c203d..2886126 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -51,6 +51,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
@@ -75,6 +76,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
@@ -336,6 +338,102 @@
}
}
+ /**
+ * Observes changes of theme settings. It will check whether to call
+ * notifyWallpaperColorsChanged by the current theme and updated theme.
+ * The light theme and dark theme are controlled by the hint values in Wallpaper colors,
+ * threrfore, if light theme mode is chosen, HINT_SUPPORTS_DARK_THEME in hint will be
+ * removed and then notify listeners.
+ */
+ private class ThemeSettingsObserver extends ContentObserver {
+
+ public ThemeSettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void startObserving(Context context) {
+ context.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.THEME_MODE),
+ false,
+ this);
+ }
+
+ public void stopObserving(Context context) {
+ context.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ onThemeSettingsChanged();
+ }
+ }
+
+ /**
+ * Check whether to call notifyWallpaperColorsChanged. Assumed that the theme mode
+ * was wallpaper theme mode and dark wallpaper was set, therefoe, the theme was dark.
+ * Then theme mode changing to dark theme mode, however, theme should not update since
+ * theme was dark already.
+ */
+ private boolean needUpdateLocked(WallpaperColors colors, int themeMode) {
+ if (colors == null) {
+ return false;
+ }
+
+ if (themeMode == mThemeMode) {
+ return false;
+ }
+
+ boolean result = true;
+ boolean supportDarkTheme =
+ (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+ switch (themeMode) {
+ case Settings.Secure.THEME_MODE_WALLPAPER:
+ if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
+ result = supportDarkTheme;
+ } else {
+ result = !supportDarkTheme;
+ }
+ break;
+ case Settings.Secure.THEME_MODE_LIGHT:
+ if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
+ result = supportDarkTheme;
+ }
+ break;
+ case Settings.Secure.THEME_MODE_DARK:
+ if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
+ result = !supportDarkTheme;
+ }
+ break;
+ default:
+ Slog.w(TAG, "unkonwn theme mode " + themeMode);
+ return false;
+ }
+ mThemeMode = themeMode;
+ return result;
+ }
+
+ void onThemeSettingsChanged() {
+ WallpaperData wallpaper;
+ synchronized (mLock) {
+ wallpaper = mWallpaperMap.get(mCurrentUserId);
+ int updatedThemeMode = Settings.Secure.getInt(
+ mContext.getContentResolver(), Settings.Secure.THEME_MODE,
+ Settings.Secure.THEME_MODE_WALLPAPER);
+
+ if (DEBUG) {
+ Slog.v(TAG, "onThemeSettingsChanged, mode = " + updatedThemeMode);
+ }
+
+ if (!needUpdateLocked(wallpaper.primaryColors, updatedThemeMode)) {
+ return;
+ }
+ }
+
+ if (wallpaper != null) {
+ notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
+ }
+ }
+
void notifyLockWallpaperChanged() {
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
@@ -413,6 +511,7 @@
}
userAllColorListeners.finishBroadcast();
}
+ wallpaperColors = getThemeColorsLocked(wallpaperColors);
}
final int count = colorListeners.size();
@@ -481,6 +580,40 @@
}
/**
+ * We can easily change theme by modified colors hint. This function will check
+ * current theme mode and return the WallpaperColors fit current theme mode.
+ * If color need modified, it will return a copied WallpaperColors which
+ * its ColorsHint is modified to fit current theme mode.
+ *
+ * @param colors a wallpaper primary colors representation
+ */
+ private WallpaperColors getThemeColorsLocked(WallpaperColors colors) {
+ if (colors == null) {
+ Slog.w(TAG, "Cannot get theme colors because WallpaperColors is null.");
+ return null;
+ }
+
+ int colorHints = colors.getColorHints();
+ boolean supportDarkTheme = (colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+ if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER ||
+ (mThemeMode == Settings.Secure.THEME_MODE_LIGHT && !supportDarkTheme) ||
+ (mThemeMode == Settings.Secure.THEME_MODE_DARK && supportDarkTheme)) {
+ return colors;
+ }
+
+ WallpaperColors themeColors = new WallpaperColors(colors.getPrimaryColor(),
+ colors.getSecondaryColor(), colors.getTertiaryColor());
+
+ if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
+ colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_THEME;
+ } else if (mThemeMode == Settings.Secure.THEME_MODE_DARK) {
+ colorHints |= WallpaperColors.HINT_SUPPORTS_DARK_THEME;
+ }
+ themeColors.setColorHints(colorHints);
+ return themeColors;
+ }
+
+ /**
* Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
* for display.
*/
@@ -676,6 +809,7 @@
final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
int mCurrentUserId = UserHandle.USER_NULL;
boolean mInAmbientMode;
+ int mThemeMode;
static class WallpaperData {
@@ -734,6 +868,7 @@
long lastDiedTime;
boolean wallpaperUpdating;
WallpaperObserver wallpaperObserver;
+ ThemeSettingsObserver themeSettingsObserver;
/**
* List of callbacks registered they should each be notified when the wallpaper is changed.
@@ -1279,6 +1414,10 @@
wallpaper.wallpaperObserver.stopWatching();
wallpaper.wallpaperObserver = null;
}
+ if (wallpaper.themeSettingsObserver != null) {
+ wallpaper.themeSettingsObserver.stopObserving(mContext);
+ wallpaper.themeSettingsObserver = null;
+ }
}
}
@@ -1362,6 +1501,13 @@
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching();
}
+ if (systemWallpaper.themeSettingsObserver == null) {
+ systemWallpaper.themeSettingsObserver = new ThemeSettingsObserver(null);
+ systemWallpaper.themeSettingsObserver.startObserving(mContext);
+ }
+ mThemeMode = Settings.Secure.getInt(
+ mContext.getContentResolver(), Settings.Secure.THEME_MODE,
+ Settings.Secure.THEME_MODE_WALLPAPER);
switchWallpaper(systemWallpaper, reply);
}
@@ -1835,7 +1981,7 @@
}
synchronized (mLock) {
- return wallpaperData.primaryColors;
+ return getThemeColorsLocked(wallpaperData.primaryColors);
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
new file mode 100644
index 0000000..c6aea88
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.server.slice;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.server.UiServiceTestCase;
+import com.android.server.slice.SliceManagerService.PackageMatchingCache;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Supplier;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class PackageMatchingCacheTest extends UiServiceTestCase {
+
+ private final Supplier<String> supplier = mock(Supplier.class);
+ private final PackageMatchingCache cache = new PackageMatchingCache(supplier);
+
+ @Test
+ public void testNulls() {
+ // Doesn't get for a null input
+ cache.matches(null);
+ verify(supplier, never()).get();
+
+ // Gets once valid input in sent.
+ cache.matches("");
+ verify(supplier).get();
+ }
+
+ @Test
+ public void testCaching() {
+ when(supplier.get()).thenReturn("ret.pkg");
+
+ assertTrue(cache.matches("ret.pkg"));
+ assertTrue(cache.matches("ret.pkg"));
+ assertTrue(cache.matches("ret.pkg"));
+
+ verify(supplier, times(1)).get();
+ }
+
+ @Test
+ public void testGetOnFailure() {
+ when(supplier.get()).thenReturn("ret.pkg");
+ assertTrue(cache.matches("ret.pkg"));
+
+ when(supplier.get()).thenReturn("other.pkg");
+ assertTrue(cache.matches("other.pkg"));
+ verify(supplier, times(2)).get();
+ }
+}