Merge "Fix tuner crash from dependencies"
diff --git a/Android.bp b/Android.bp
index 391bcd5..cd0720d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -634,6 +634,7 @@
"wifi/java/android/net/wifi/rtt/IRttCallback.aidl",
"wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl",
"wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl",
+ "wifi/java/android/net/wifi/IDppCallback.aidl",
"wifi/java/android/net/wifi/IWifiScanner.aidl",
"packages/services/PacProcessor/com/android/net/IProxyService.aidl",
"packages/services/Proxy/com/android/net/IProxyCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index c107e58..fad607c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29555,6 +29555,7 @@
method public int getWifiState();
method public boolean is5GHzBandSupported();
method public boolean isDeviceToApRttSupported();
+ method public boolean isDppSupported();
method public boolean isEnhancedPowerReportingSupported();
method public boolean isOweSupported();
method public boolean isP2pSupported();
diff --git a/api/system-current.txt b/api/system-current.txt
index 7f3c152..f130c69 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1221,7 +1221,6 @@
public abstract class PackageManager {
method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
- method public boolean canSuspendPackage(java.lang.String);
method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
method public android.content.pm.ApplicationInfo getApplicationInfoAsUser(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method public android.content.pm.dex.ArtManager getArtManager();
@@ -1235,6 +1234,7 @@
method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String);
method public abstract int getIntentVerificationStatusAsUser(java.lang.String, int);
method public abstract int getPermissionFlags(java.lang.String, java.lang.String, android.os.UserHandle);
+ method public java.lang.String[] getUnsuspendablePackages(java.lang.String[]);
method public abstract void grantRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public abstract int installExistingPackage(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract int installExistingPackage(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -3001,6 +3001,7 @@
field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
field public static final int FLAG_FROM_KEY = 65536; // 0x10000
+ field public static final int SUCCESS = 0; // 0x0
}
public static abstract class AudioManager.AudioServerStateCallback {
@@ -3117,8 +3118,10 @@
method public int detachMixes(java.util.List<android.media.audiopolicy.AudioMix>);
method public int getFocusDuckingBehavior();
method public int getStatus();
+ method public int removeUidDeviceAffinity(int);
method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setRegistration(java.lang.String);
+ method public int setUidDeviceAffinity(int, java.util.List<android.media.AudioDeviceInfo>);
method public java.lang.String toLogFriendlyString();
field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
@@ -3715,6 +3718,26 @@
package android.net.wifi {
+ public abstract class DppStatusCallback {
+ ctor public DppStatusCallback();
+ method public abstract void onConfiguratorSuccess(int);
+ method public abstract void onEnrolleeSuccess(int);
+ method public abstract void onFailure(int);
+ method public abstract void onProgress(int);
+ field public static final int DPP_EVENT_FAILURE = -7; // 0xfffffff9
+ field public static final int DPP_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
+ field public static final int DPP_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
+ field public static final int DPP_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
+ field public static final int DPP_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
+ field public static final int DPP_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
+ field public static final int DPP_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd
+ field public static final int DPP_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
+ field public static final int DPP_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
+ field public static final int DPP_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0; // 0x0
+ field public static final int DPP_EVENT_PROGRESS_RESPONSE_PENDING = 1; // 0x1
+ field public static final int DPP_EVENT_SUCCESS_CONFIGURATION_SENT = 0; // 0x0
+ }
+
public deprecated class RttManager {
method public void disableResponder(android.net.wifi.RttManager.ResponderCallback);
method public void enableResponder(android.net.wifi.RttManager.ResponderCallback);
@@ -3944,7 +3967,10 @@
method public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public void setDeviceMobilityState(int);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
+ method public void startDppAsConfiguratorInitiator(java.lang.String, int, int, android.os.Handler, android.net.wifi.DppStatusCallback);
+ method public void startDppAsEnrolleeInitiator(java.lang.String, android.os.Handler, android.net.wifi.DppStatusCallback);
method public boolean startScan(android.os.WorkSource);
+ method public void stopDppSession();
method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
field public static final int CHANGE_REASON_ADDED = 0; // 0x0
field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2
@@ -3954,6 +3980,8 @@
field public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; // 0x2
field public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; // 0x3
field public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; // 0x0
+ field public static final int DPP_NETWORK_ROLE_AP = 1; // 0x1
+ field public static final int DPP_NETWORK_ROLE_STA = 0; // 0x0
field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason";
field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
@@ -7955,6 +7983,7 @@
method public void callDrawGlFunction(android.graphics.Canvas, long, java.lang.Runnable);
method public boolean canInvokeDrawGlFunctor(android.view.View);
method public void detachDrawGlFunctor(android.view.View, long);
+ method public void drawWebViewFunctor(android.graphics.Canvas, int);
method public android.app.Application getApplication();
method public java.lang.String getDataDirectorySuffix();
method public java.lang.String getErrorString(android.content.Context, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index c1e4162..9c51c9f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -72,6 +72,7 @@
method public void resizeStack(int, android.graphics.Rect) throws java.lang.SecurityException;
method public void resizeStack(int, android.graphics.Rect, boolean);
method public void resizeTask(int, android.graphics.Rect);
+ method public void setDisplayToSingleTaskInstance(int);
method public void setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
method public void setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) throws java.lang.SecurityException;
method public void startSystemLockTaskMode(int);
@@ -1153,6 +1154,20 @@
method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
}
+ public final class CompositeUserData implements android.os.Parcelable {
+ ctor public CompositeUserData(android.service.autofill.UserData, android.service.autofill.UserData);
+ method public int describeContents();
+ method public java.lang.String[] getCategoryIds();
+ method public android.os.Bundle getDefaultFieldClassificationArgs();
+ method public java.lang.String getFieldClassificationAlgorithm();
+ method public java.lang.String getFieldClassificationAlgorithmForCategory(java.lang.String);
+ method public android.util.ArrayMap<java.lang.String, java.lang.String> getFieldClassificationAlgorithms();
+ method public android.util.ArrayMap<java.lang.String, android.os.Bundle> getFieldClassificationArgs();
+ method public java.lang.String[] getValues();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.autofill.CompositeUserData> CREATOR;
+ }
+
public final class CustomDescription implements android.os.Parcelable {
method public android.util.SparseArray<android.service.autofill.InternalOnClickAction> getActions();
}
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 498eebc..04d4f9a 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -114,7 +114,7 @@
virtual void shutdown() {}
};
- BootAnimation(sp<Callbacks> callbacks);
+ explicit BootAnimation(sp<Callbacks> callbacks);
sp<SurfaceComposerClient> session() const;
@@ -128,7 +128,7 @@
class TimeCheckThread : public Thread {
public:
- TimeCheckThread(BootAnimation* bootAnimation);
+ explicit TimeCheckThread(BootAnimation* bootAnimation);
virtual ~TimeCheckThread();
private:
virtual status_t readyToRun();
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index fe7099b..abe18ba 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -23,6 +23,7 @@
],
tidy_flags: [
"-system-headers",
+ "-warnings-as-errors=*",
],
}
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index f0b751d..d610f66 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -136,7 +136,7 @@
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power.stats@1.0",
- "android.hardware.thermal@1.0",
+ "android.hardware.thermal@2.0",
"libpackagelistparser",
"libsysutils",
"libcutils",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e541543..5c53a3a 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -2789,13 +2789,14 @@
* frameworks/base/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
*/
message Temperature {
- // The type of temperature being reported. Eg. CPU, GPU, SKIN, BATTERY.
+ // The type of temperature being reported. Eg. CPU, GPU, SKIN, BATTERY, BCL_.
optional android.os.TemperatureTypeEnum sensor_location = 1;
// The name of the temperature source. Eg. CPU0
optional string sensor_name = 2;
// Temperature in tenths of a degree C.
+ // For BCL, it is decimillivolt, decimilliamps, and percentage * 10.
optional int32 temperature_deci_celsius = 3;
}
diff --git a/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp b/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
index 33a17de..53709f1 100644
--- a/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourceThermalManagerPuller.cpp
@@ -17,7 +17,7 @@
#define DEBUG false // STOPSHIP if true
#include "Log.h"
-#include <android/hardware/thermal/1.0/IThermal.h>
+#include <android/hardware/thermal/2.0/IThermal.h>
#include "external/ResourceThermalManagerPuller.h"
#include "external/StatsPuller.h"
@@ -31,10 +31,11 @@
using android::hardware::hidl_death_recipient;
using android::hardware::hidl_vec;
using android::hidl::base::V1_0::IBase;
-using android::hardware::thermal::V1_0::IThermal;
-using android::hardware::thermal::V1_0::Temperature;
-using android::hardware::thermal::V1_0::ThermalStatus;
-using android::hardware::thermal::V1_0::ThermalStatusCode;
+using ::android::hardware::thermal::V2_0::IThermal;
+using ::android::hardware::thermal::V2_0::Temperature;
+using ::android::hardware::thermal::V2_0::TemperatureType;
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
using android::hardware::Return;
using android::hardware::Void;
@@ -49,7 +50,7 @@
namespace statsd {
bool getThermalHalLocked();
-sp<android::hardware::thermal::V1_0::IThermal> gThermalHal = nullptr;
+sp<android::hardware::thermal::V2_0::IThermal> gThermalHal = nullptr;
std::mutex gThermalHalMutex;
struct ThermalHalDeathRecipient : virtual public hidl_death_recipient {
@@ -107,7 +108,7 @@
data->clear();
bool resultSuccess = true;
- Return<void> ret = gThermalHal->getTemperatures(
+ Return<void> ret = gThermalHal->getCurrentTemperatures(false, TemperatureType::SKIN,
[&](ThermalStatus status, const hidl_vec<Temperature>& temps) {
if (status.code != ThermalStatusCode::SUCCESS) {
ALOGE("Failed to get temperatures from ThermalHAL. Status: %d", status.code);
@@ -121,7 +122,7 @@
ptr->write((static_cast<int>(temps[i].type)));
ptr->write(temps[i].name);
// Convert the temperature to an int.
- int32_t temp = static_cast<int>(temps[i].currentValue * 10);
+ int32_t temp = static_cast<int>(temps[i].value * 10);
ptr->write(temp);
ptr->init();
data->push_back(ptr);
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 4d8c856..7eab5db 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -430,4 +430,17 @@
e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Makes the display with the given id a single task instance display. I.e the display can only
+ * contain one task.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+ public void setDisplayToSingleTaskInstance(int displayId) {
+ try {
+ getService().setDisplayToSingleTaskInstance(displayId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 680fed8..0b5776e 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -83,6 +83,9 @@
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
private Surface mTmpSurface = new Surface();
+ /** The ActivityView is only allowed to contain one task. */
+ private final boolean mSingleTaskInstance;
+
@UnsupportedAppUsage
public ActivityView(Context context) {
this(context, null /* attrs */);
@@ -93,7 +96,13 @@
}
public ActivityView(Context context, AttributeSet attrs, int defStyle) {
+ this(context, attrs, defStyle, false /*singleTaskInstance*/);
+ }
+
+ public ActivityView(
+ Context context, AttributeSet attrs, int defStyle, boolean singleTaskInstance) {
super(context, attrs, defStyle);
+ mSingleTaskInstance = singleTaskInstance;
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
@@ -379,6 +388,9 @@
try {
wm.reparentDisplayContent(displayId, mRootSurfaceControl.getHandle());
wm.dontOverrideDisplayInfo(displayId);
+ if (mSingleTaskInstance) {
+ mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
+ }
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 17529a6..94983e1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2299,9 +2299,9 @@
}
@Override
- public boolean canSuspendPackage(String packageName) {
+ public String[] getUnsuspendablePackages(String[] packageNames) {
try {
- return mPM.canSuspendPackageForUser(packageName, mContext.getUserId());
+ return mPM.getUnsuspendablePackagesForUser(packageNames, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index f549e18..dd87dc3 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -452,4 +452,10 @@
* Clears launch params for given packages.
*/
void clearLaunchParamsForPackages(in List<String> packageNames);
+
+ /**
+ * Makes the display with the given id a single task instance display. I.e the display can only
+ * contain one task.
+ */
+ void setDisplayToSingleTaskInstance(int displayId);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1e3908c..3492200 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -9169,7 +9169,7 @@
* @param extras The new set of extras in the Intent, or null to erase
* all extras.
*/
- public @NonNull Intent replaceExtras(@NonNull Bundle extras) {
+ public @NonNull Intent replaceExtras(@Nullable Bundle extras) {
mExtras = extras != null ? new Bundle(extras) : null;
return this;
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 502fb78..2978058 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -639,6 +639,21 @@
*/
public static final int PRIVATE_FLAG_HAS_FRAGILE_USER_DATA = 1 << 24;
+ /**
+ * Indicate whether this application prefers code integrity, that is, run only code that is
+ * signed. This requires android:extractNativeLibs to be "false", as well as .dex and .so (if
+ * any) stored uncompressed inside the APK, which is signed. At run time, the implications
+ * include:
+ *
+ * <ul>
+ * <li>ART will JIT the dex code directly from the APK. There may be performance characteristic
+ * changes depend on the actual workload.
+ * </ul>
+ *
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_PREFER_CODE_INTEGRITY = 1 << 25;
+
/** @hide */
@IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -654,6 +669,7 @@
PRIVATE_FLAG_ISOLATED_SPLIT_LOADING,
PRIVATE_FLAG_OEM,
PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
+ PRIVATE_FLAG_PREFER_CODE_INTEGRITY,
PRIVATE_FLAG_PRIVILEGED,
PRIVATE_FLAG_PRODUCT,
PRIVATE_FLAG_PRODUCT_SERVICES,
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a4ea513..64a4479b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -277,7 +277,7 @@
in PersistableBundle appExtras, in PersistableBundle launcherExtras,
in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
- boolean canSuspendPackageForUser(String packageName, int userId);
+ String[] getUnsuspendablePackagesForUser(in String[] packageNames, int userId);
boolean isPackageSuspendedForUser(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2608796..6110557 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5969,27 +5969,28 @@
}
/**
- * Returns whether or not a given package can be suspended via a call to {@link
+ * Returns any packages in a given set of packages that cannot be suspended via a call to {@link
* #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
* SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical
* packages to keep the device in a functioning state, e.g. the default dialer.
* Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this api.
*
* <p>
- * Note that this set of critical packages can change with time, so <em>a value of {@code true}
- * returned by this api does not guarantee that a following call to {@link
- * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
- * SuspendDialogInfo) setPackagesSuspended} for the same package will succeed</em>, especially
- * if considerable time elapsed between the two calls.
+ * Note that this set of critical packages can change with time, so even though a package name
+ * was not returned by this call, it does not guarantee that a subsequent call to
+ * {@link #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+ * SuspendDialogInfo) setPackagesSuspended} for that package will succeed, especially if
+ * significant time elapsed between the two calls.
*
- * @param packageName The package to check.
- * @return {@code true} if the given package can be suspended, {@code false} otherwise.
+ * @param packageNames The packages to check.
+ * @return A list of packages that can not be currently suspended by the system.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.SUSPEND_APPS)
- public boolean canSuspendPackage(@NonNull String packageName) {
- throw new UnsupportedOperationException("canSuspendPackage not implemented");
+ @NonNull
+ public String[] getUnsuspendablePackages(@NonNull String[] packageNames) {
+ throw new UnsupportedOperationException("canSuspendPackages not implemented");
}
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e38b294..2b266b7 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -475,6 +475,7 @@
public final boolean extractNativeLibs;
public final boolean isolatedSplits;
public final boolean isSplitRequired;
+ public final boolean preferCodeIntegrity;
public ApkLite(String codePath, String packageName, String splitName,
boolean isFeatureSplit,
@@ -483,7 +484,7 @@
int revisionCode, int installLocation, List<VerifierInfo> verifiers,
SigningDetails signingDetails, boolean coreApp,
boolean debuggable, boolean multiArch, boolean use32bitAbi,
- boolean extractNativeLibs, boolean isolatedSplits) {
+ boolean preferCodeIntegrity, boolean extractNativeLibs, boolean isolatedSplits) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -500,6 +501,7 @@
this.debuggable = debuggable;
this.multiArch = multiArch;
this.use32bitAbi = use32bitAbi;
+ this.preferCodeIntegrity = preferCodeIntegrity;
this.extractNativeLibs = extractNativeLibs;
this.isolatedSplits = isolatedSplits;
this.isSplitRequired = isSplitRequired;
@@ -1722,6 +1724,7 @@
boolean isolatedSplits = false;
boolean isFeatureSplit = false;
boolean isSplitRequired = false;
+ boolean preferCodeIntegrity = false;
String configForSplit = null;
String usesSplitName = null;
@@ -1784,6 +1787,9 @@
if ("extractNativeLibs".equals(attr)) {
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
}
+ if ("preferCodeIntegrity".equals(attr)) {
+ preferCodeIntegrity = attrs.getAttributeBooleanValue(i, false);
+ }
}
} else if (TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
@@ -1800,10 +1806,16 @@
}
}
+ if (preferCodeIntegrity && extractNativeLibs) {
+ throw new PackageParserException(
+ PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "Can't request both preferCodeIntegrity and extractNativeLibs");
+ }
+
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
- multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
+ multiArch, use32bitAbi, preferCodeIntegrity, extractNativeLibs, isolatedSplits);
}
/**
@@ -3655,6 +3667,12 @@
}
if (sa.getBoolean(
+ R.styleable.AndroidManifestApplication_preferCodeIntegrity,
+ false)) {
+ ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY;
+ }
+
+ if (sa.getBoolean(
R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index a4c1332..dd782ec 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -60,6 +60,13 @@
return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
}
+ /**
+ * Returns {@code true} if display white balance is supported by the device.
+ */
+ public static boolean isDisplayWhiteBalanceAvailable(Context context) {
+ return context.getResources().getBoolean(R.bool.config_displayWhiteBalanceAvailable);
+ }
+
private static class ColorDisplayManagerInternal {
private static ColorDisplayManagerInternal sInstance;
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index bac23b3..1630b06 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -975,14 +975,11 @@
mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
}
final String msg = getAcquiredString(mContext, acquireInfo, vendorCode);
- if (msg == null) {
- return;
- }
final int clientInfo = acquireInfo == FACE_ACQUIRED_VENDOR
? (vendorCode + FACE_ACQUIRED_VENDOR_BASE) : acquireInfo;
if (mEnrollmentCallback != null) {
mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
- } else if (mAuthenticationCallback != null) {
+ } else if (mAuthenticationCallback != null && msg != null) {
mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
}
}
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index f3810bd..d979309 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -58,7 +58,7 @@
private static final boolean DEBUG = false;
private static final String TAG = "GraphicsEnvironment";
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
- private static final String PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
+ private static final String GUP_WHITELIST_FILENAME = "whitelist.txt";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -482,7 +482,7 @@
String applicationPackageName = context.getPackageName();
String devOptInApplicationName = coreSettings.getString(
- Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+ Settings.Global.GUP_DEV_OPT_IN_APPS);
boolean devOptIn = applicationPackageName.equals(devOptInApplicationName);
boolean whitelisted = onWhitelist(context, driverPackageName, ai.packageName);
if (!devOptIn && !whitelisted) {
@@ -567,22 +567,11 @@
private static boolean onWhitelist(Context context, String driverPackageName,
String applicationPackageName) {
- String whitelistName = SystemProperties.get(PROPERTY_GFX_DRIVER_WHITELIST);
-
- // Empty whitelist implies no updatable graphics driver. Typically, the pre-installed
- // updatable graphics driver is supposed to be a place holder and contains no graphics
- // driver and whitelist.
- if (whitelistName == null || whitelistName.isEmpty()) {
- if (DEBUG) {
- Log.w(TAG, "No whitelist found.");
- }
- return false;
- }
try {
Context driverContext = context.createPackageContext(driverPackageName,
Context.CONTEXT_RESTRICTED);
AssetManager assets = driverContext.getAssets();
- InputStream stream = assets.open(whitelistName);
+ InputStream stream = assets.open(GUP_WHITELIST_FILENAME);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
for (String packageName; (packageName = reader.readLine()) != null; ) {
if (packageName.equals(applicationPackageName)) {
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 457453f..c4e2b12 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1338,7 +1338,7 @@
public static final String insertImage(ContentResolver cr, Bitmap source,
String title, String description) {
ContentValues values = new ContentValues();
- values.put(Images.Media.TITLE, title);
+ values.put(Images.Media.DISPLAY_NAME, title);
values.put(Images.Media.DESCRIPTION, description);
values.put(Images.Media.MIME_TYPE, "image/jpeg");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d93985c..52effb3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7957,6 +7957,15 @@
"night_display_last_activated_time";
/**
+ * Control whether display white balance is currently enabled.
+ * @hide
+ */
+ public static final String DISPLAY_WHITE_BALANCE_ENABLED = "display_white_balance_enabled";
+
+ private static final Validator DISPLAY_WHITE_BALANCE_ENABLED_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
+ /**
* Names of the service components that the current user has explicitly allowed to
* be a VR mode listener, separated by ':'.
*
@@ -8405,6 +8414,7 @@
NIGHT_DISPLAY_CUSTOM_END_TIME,
NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_AUTO_MODE,
+ DISPLAY_WHITE_BALANCE_ENABLED,
SYNC_PARENT_SOUNDS,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
SWIPE_UP_TO_SWITCH_APPS_ENABLED,
@@ -8552,6 +8562,7 @@
VALIDATORS.put(NIGHT_DISPLAY_COLOR_TEMPERATURE,
NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR);
VALIDATORS.put(NIGHT_DISPLAY_AUTO_MODE, NIGHT_DISPLAY_AUTO_MODE_VALIDATOR);
+ VALIDATORS.put(DISPLAY_WHITE_BALANCE_ENABLED, DISPLAY_WHITE_BALANCE_ENABLED_VALIDATOR);
VALIDATORS.put(SYNC_PARENT_SOUNDS, SYNC_PARENT_SOUNDS_VALIDATOR);
VALIDATORS.put(CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR);
@@ -11971,11 +11982,16 @@
"angle_gl_driver_selection_values";
/**
- * App that is selected to use updated graphics driver.
+ * Apps that are selected to use Game Update Package.
* @hide
*/
- public static final String UPDATED_GFX_DRIVER_DEV_OPT_IN_APP =
- "updated_gfx_driver_dev_opt_in_app";
+ public static final String GUP_DEV_OPT_IN_APPS = "gup_dev_opt_in_apps";
+
+ /**
+ * Apps on the black list that are forbidden to useGame Update Package.
+ * @hide
+ */
+ public static final String GUP_BLACK_LIST = "gup_black_list";
/**
* Ordered GPU debug layer list for Vulkan
diff --git a/core/java/android/service/autofill/CompositeUserData.java b/core/java/android/service/autofill/CompositeUserData.java
new file mode 100644
index 0000000..2df4ddf
--- /dev/null
+++ b/core/java/android/service/autofill/CompositeUserData.java
@@ -0,0 +1,211 @@
+/*
+ * 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 android.service.autofill;
+
+import static android.view.autofill.Helper.sDebug;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Holds both a generic and package-specific userData used for
+ * <a href="AutofillService.html#FieldClassification">field classification</a>.
+ *
+ * @hide
+ */
+@TestApi
+public final class CompositeUserData implements FieldClassificationUserData, Parcelable {
+
+ private final UserData mGenericUserData;
+ private final UserData mPackageUserData;
+
+ private final String[] mCategories;
+ private final String[] mValues;
+
+ public CompositeUserData(@Nullable UserData genericUserData,
+ @NonNull UserData packageUserData) {
+ mGenericUserData = genericUserData;
+ mPackageUserData = packageUserData;
+
+ final String[] packageCategoryIds = mPackageUserData.getCategoryIds();
+ final String[] packageValues = mPackageUserData.getValues();
+
+ final ArrayList<String> categoryIds = new ArrayList<>(packageCategoryIds.length);
+ final ArrayList<String> values = new ArrayList<>(packageValues.length);
+
+ Collections.addAll(categoryIds, packageCategoryIds);
+ Collections.addAll(values, packageValues);
+
+ if (mGenericUserData != null) {
+ final String[] genericCategoryIds = mGenericUserData.getCategoryIds();
+ final String[] genericValues = mGenericUserData.getValues();
+ final int size = mGenericUserData.getCategoryIds().length;
+ for (int i = 0; i < size; i++) {
+ if (!categoryIds.contains(genericCategoryIds[i])) {
+ categoryIds.add(genericCategoryIds[i]);
+ values.add(genericValues[i]);
+ }
+ }
+ }
+
+ mCategories = new String[categoryIds.size()];
+ categoryIds.toArray(mCategories);
+ mValues = new String[values.size()];
+ values.toArray(mValues);
+ }
+
+ @Nullable
+ @Override
+ public String getFieldClassificationAlgorithm() {
+ final String packageDefaultAlgo = mPackageUserData.getFieldClassificationAlgorithm();
+ if (packageDefaultAlgo != null) {
+ return packageDefaultAlgo;
+ } else {
+ return mGenericUserData == null ? null :
+ mGenericUserData.getFieldClassificationAlgorithm();
+ }
+ }
+
+ @Override
+ public Bundle getDefaultFieldClassificationArgs() {
+ final Bundle packageDefaultArgs = mPackageUserData.getDefaultFieldClassificationArgs();
+ if (packageDefaultArgs != null) {
+ return packageDefaultArgs;
+ } else {
+ return mGenericUserData == null ? null :
+ mGenericUserData.getDefaultFieldClassificationArgs();
+ }
+ }
+
+ @Nullable
+ @Override
+ public String getFieldClassificationAlgorithmForCategory(@NonNull String categoryId) {
+ Preconditions.checkNotNull(categoryId);
+ final ArrayMap<String, String> categoryAlgorithms = getFieldClassificationAlgorithms();
+ if (categoryAlgorithms == null || !categoryAlgorithms.containsKey(categoryId)) {
+ return null;
+ }
+ return categoryAlgorithms.get(categoryId);
+ }
+
+ @Override
+ public ArrayMap<String, String> getFieldClassificationAlgorithms() {
+ final ArrayMap<String, String> packageAlgos = mPackageUserData
+ .getFieldClassificationAlgorithms();
+ final ArrayMap<String, String> genericAlgos = mGenericUserData == null ? null :
+ mGenericUserData.getFieldClassificationAlgorithms();
+
+ ArrayMap<String, String> categoryAlgorithms = null;
+ if (packageAlgos != null || genericAlgos != null) {
+ categoryAlgorithms = new ArrayMap<>();
+ if (genericAlgos != null) {
+ categoryAlgorithms.putAll(genericAlgos);
+ }
+ if (packageAlgos != null) {
+ categoryAlgorithms.putAll(packageAlgos);
+ }
+ }
+
+ return categoryAlgorithms;
+ }
+
+ @Override
+ public ArrayMap<String, Bundle> getFieldClassificationArgs() {
+ final ArrayMap<String, Bundle> packageArgs = mPackageUserData.getFieldClassificationArgs();
+ final ArrayMap<String, Bundle> genericArgs = mGenericUserData == null ? null :
+ mGenericUserData.getFieldClassificationArgs();
+
+ ArrayMap<String, Bundle> categoryArgs = null;
+ if (packageArgs != null || genericArgs != null) {
+ categoryArgs = new ArrayMap<>();
+ if (genericArgs != null) {
+ categoryArgs.putAll(genericArgs);
+ }
+ if (packageArgs != null) {
+ categoryArgs.putAll(packageArgs);
+ }
+ }
+
+ return categoryArgs;
+ }
+
+ @Override
+ public String[] getCategoryIds() {
+ return mCategories;
+ }
+
+ @Override
+ public String[] getValues() {
+ return mValues;
+ }
+
+ /////////////////////////////////////
+ // Object "contract" methods. //
+ /////////////////////////////////////
+ @Override
+ public String toString() {
+ if (!sDebug) return super.toString();
+
+ // OK to print UserData because UserData.toString() is PII-aware
+ final StringBuilder builder = new StringBuilder("genericUserData=")
+ .append(mGenericUserData)
+ .append(", packageUserData=").append(mPackageUserData);
+ return builder.toString();
+ }
+
+ /////////////////////////////////////
+ // Parcelable "contract" methods. //
+ /////////////////////////////////////
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeParcelable(mGenericUserData, 0);
+ parcel.writeParcelable(mPackageUserData, 0);
+ }
+
+ public static final Parcelable.Creator<CompositeUserData> CREATOR =
+ new Parcelable.Creator<CompositeUserData>() {
+ @Override
+ public CompositeUserData createFromParcel(Parcel parcel) {
+ // Always go through the builder to ensure the data ingested by
+ // the system obeys the contract of the builder to avoid attacks
+ // using specially crafted parcels.
+ final UserData genericUserData = parcel.readParcelable(null);
+ final UserData packageUserData = parcel.readParcelable(null);
+ return new CompositeUserData(genericUserData, packageUserData);
+ }
+
+ @Override
+ public CompositeUserData[] newArray(int size) {
+ return new CompositeUserData[size];
+ }
+ };
+}
diff --git a/core/java/android/service/autofill/FieldClassificationUserData.java b/core/java/android/service/autofill/FieldClassificationUserData.java
new file mode 100644
index 0000000..3d6cac4
--- /dev/null
+++ b/core/java/android/service/autofill/FieldClassificationUserData.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.service.autofill;
+
+import android.os.Bundle;
+import android.util.ArrayMap;
+
+/**
+ * Class used to define a generic UserData for field classification
+ *
+ * @hide
+ */
+public interface FieldClassificationUserData {
+ /**
+ * Gets the name of the default algorithm that is used to calculate
+ * {@link FieldClassification.Match#getScore()} match scores}.
+ */
+ String getFieldClassificationAlgorithm();
+
+ /**
+ * Gets the default field classification args.
+ */
+ Bundle getDefaultFieldClassificationArgs();
+
+ /**
+ * Gets the name of the field classification algorithm for a specific category.
+ *
+ * @param categoryId id of the specific category.
+ */
+ String getFieldClassificationAlgorithmForCategory(String categoryId);
+
+ /**
+ * Gets all field classification algorithms for specific categories.
+ */
+ ArrayMap<String, String> getFieldClassificationAlgorithms();
+
+ /**
+ * Gets all field classification args for specific categories.
+ */
+ ArrayMap<String, Bundle> getFieldClassificationArgs();
+
+ /**
+ * Gets all category ids
+ */
+ String[] getCategoryIds();
+
+ /**
+ * Gets all string values for field classification
+ */
+ String[] getValues();
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index d408e9a..93ee8c3 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -516,6 +516,9 @@
/**
* Sets a specific {@link UserData} for field classification for this request only.
*
+ * <p>Any fields in this UserData will override corresponding fields in the generic
+ * UserData object
+ *
* @return this builder
* @throws IllegalStateException if the FillResponse
* {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 37f1923..a793e09 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -48,7 +48,7 @@
* Defines the user data used for
* <a href="AutofillService.html#FieldClassification">field classification</a>.
*/
-public final class UserData implements Parcelable {
+public final class UserData implements FieldClassificationUserData, Parcelable {
private static final String TAG = "UserData";
@@ -86,11 +86,13 @@
* {@link Match#getScore()} match scores}.
*/
@Nullable
+ @Override
public String getFieldClassificationAlgorithm() {
return mDefaultAlgorithm;
}
/** @hide */
+ @Override
public Bundle getDefaultFieldClassificationArgs() {
return mDefaultArgs;
}
@@ -104,6 +106,7 @@
* @return String name of algorithm, null if none found.
*/
@Nullable
+ @Override
public String getFieldClassificationAlgorithmForCategory(@NonNull String categoryId) {
Preconditions.checkNotNull(categoryId);
if (mCategoryAlgorithms == null || !mCategoryAlgorithms.containsKey(categoryId)) {
@@ -120,22 +123,26 @@
}
/** @hide */
+ @Override
public String[] getCategoryIds() {
return mCategoryIds;
}
/** @hide */
+ @Override
public String[] getValues() {
return mValues;
}
/** @hide */
@TestApi
+ @Override
public ArrayMap<String, String> getFieldClassificationAlgorithms() {
return mCategoryAlgorithms;
}
/** @hide */
+ @Override
public ArrayMap<String, Bundle> getFieldClassificationArgs() {
return mCategoryArgs;
}
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
index 5524506..f31ddd9 100644
--- a/core/java/android/util/Range.java
+++ b/core/java/android/util/Range.java
@@ -28,7 +28,7 @@
* "integers from 1 to 100 inclusive."
* </p>
* <p>
- * All ranges are bounded, and the left side of the range is always {@code >=}
+ * All ranges are bounded, and the left side of the range is always {@code <=}
* the right side of the range.
* </p>
*
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index a4d3ce7..be81c06 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -921,129 +921,129 @@
AttributeSet attrs) throws XmlPullParserException, IOException {
int type;
- if (parent instanceof ViewGroup) {
- // Apply a theme wrapper, if requested. This is sort of a weird
- // edge case, since developers think the <include> overwrites
- // values in the AttributeSet of the included View. So, if the
- // included View has a theme attribute, we'll need to ignore it.
- final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
- final int themeResId = ta.getResourceId(0, 0);
- final boolean hasThemeOverride = themeResId != 0;
- if (hasThemeOverride) {
- context = new ContextThemeWrapper(context, themeResId);
- }
- ta.recycle();
-
- // If the layout is pointing to a theme attribute, we have to
- // massage the value to get a resource identifier out of it.
- int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
- if (layout == 0) {
- final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
- if (value == null || value.length() <= 0) {
- throw new InflateException("You must specify a layout in the"
- + " include tag: <include layout=\"@layout/layoutID\" />");
- }
-
- // Attempt to resolve the "?attr/name" string to an attribute
- // within the default (e.g. application) package.
- layout = context.getResources().getIdentifier(
- value.substring(1), "attr", context.getPackageName());
-
- }
-
- // The layout might be referencing a theme attribute.
- if (mTempValue == null) {
- mTempValue = new TypedValue();
- }
- if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
- layout = mTempValue.resourceId;
- }
-
- if (layout == 0) {
- final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
- throw new InflateException("You must specify a valid layout "
- + "reference. The layout ID " + value + " is not valid.");
- } else {
- final XmlResourceParser childParser = context.getResources().getLayout(layout);
-
- try {
- final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
-
- while ((type = childParser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty.
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new InflateException(childParser.getPositionDescription() +
- ": No start tag found!");
- }
-
- final String childName = childParser.getName();
-
- if (TAG_MERGE.equals(childName)) {
- // The <merge> tag doesn't support android:theme, so
- // nothing special to do here.
- rInflate(childParser, parent, context, childAttrs, false);
- } else {
- final View view = createViewFromTag(parent, childName,
- context, childAttrs, hasThemeOverride);
- final ViewGroup group = (ViewGroup) parent;
-
- final TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.Include);
- final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
- final int visibility = a.getInt(R.styleable.Include_visibility, -1);
- a.recycle();
-
- // We try to load the layout params set in the <include /> tag.
- // If the parent can't generate layout params (ex. missing width
- // or height for the framework ViewGroups, though this is not
- // necessarily true of all ViewGroups) then we expect it to throw
- // a runtime exception.
- // We catch this exception and set localParams accordingly: true
- // means we successfully loaded layout params from the <include>
- // tag, false means we need to rely on the included layout params.
- ViewGroup.LayoutParams params = null;
- try {
- params = group.generateLayoutParams(attrs);
- } catch (RuntimeException e) {
- // Ignore, just fail over to child attrs.
- }
- if (params == null) {
- params = group.generateLayoutParams(childAttrs);
- }
- view.setLayoutParams(params);
-
- // Inflate all children.
- rInflateChildren(childParser, view, childAttrs, true);
-
- if (id != View.NO_ID) {
- view.setId(id);
- }
-
- switch (visibility) {
- case 0:
- view.setVisibility(View.VISIBLE);
- break;
- case 1:
- view.setVisibility(View.INVISIBLE);
- break;
- case 2:
- view.setVisibility(View.GONE);
- break;
- }
-
- group.addView(view);
- }
- } finally {
- childParser.close();
- }
- }
- } else {
+ if (!(parent instanceof ViewGroup)) {
throw new InflateException("<include /> can only be used inside of a ViewGroup");
}
+ // Apply a theme wrapper, if requested. This is sort of a weird
+ // edge case, since developers think the <include> overwrites
+ // values in the AttributeSet of the included View. So, if the
+ // included View has a theme attribute, we'll need to ignore it.
+ final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
+ final int themeResId = ta.getResourceId(0, 0);
+ final boolean hasThemeOverride = themeResId != 0;
+ if (hasThemeOverride) {
+ context = new ContextThemeWrapper(context, themeResId);
+ }
+ ta.recycle();
+
+ // If the layout is pointing to a theme attribute, we have to
+ // massage the value to get a resource identifier out of it.
+ int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
+ if (layout == 0) {
+ final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
+ if (value == null || value.length() <= 0) {
+ throw new InflateException("You must specify a layout in the"
+ + " include tag: <include layout=\"@layout/layoutID\" />");
+ }
+
+ // Attempt to resolve the "?attr/name" string to an attribute
+ // within the default (e.g. application) package.
+ layout = context.getResources().getIdentifier(
+ value.substring(1), "attr", context.getPackageName());
+
+ }
+
+ // The layout might be referencing a theme attribute.
+ if (mTempValue == null) {
+ mTempValue = new TypedValue();
+ }
+ if (layout != 0 && context.getTheme().resolveAttribute(layout, mTempValue, true)) {
+ layout = mTempValue.resourceId;
+ }
+
+ if (layout == 0) {
+ final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
+ throw new InflateException("You must specify a valid layout "
+ + "reference. The layout ID " + value + " is not valid.");
+ }
+
+ final XmlResourceParser childParser = context.getResources().getLayout(layout);
+
+ try {
+ final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
+
+ while ((type = childParser.next()) != XmlPullParser.START_TAG &&
+ type != XmlPullParser.END_DOCUMENT) {
+ // Empty.
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new InflateException(childParser.getPositionDescription() +
+ ": No start tag found!");
+ }
+
+ final String childName = childParser.getName();
+
+ if (TAG_MERGE.equals(childName)) {
+ // The <merge> tag doesn't support android:theme, so
+ // nothing special to do here.
+ rInflate(childParser, parent, context, childAttrs, false);
+ } else {
+ final View view = createViewFromTag(parent, childName,
+ context, childAttrs, hasThemeOverride);
+ final ViewGroup group = (ViewGroup) parent;
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.Include);
+ final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
+ final int visibility = a.getInt(R.styleable.Include_visibility, -1);
+ a.recycle();
+
+ // We try to load the layout params set in the <include /> tag.
+ // If the parent can't generate layout params (ex. missing width
+ // or height for the framework ViewGroups, though this is not
+ // necessarily true of all ViewGroups) then we expect it to throw
+ // a runtime exception.
+ // We catch this exception and set localParams accordingly: true
+ // means we successfully loaded layout params from the <include>
+ // tag, false means we need to rely on the included layout params.
+ ViewGroup.LayoutParams params = null;
+ try {
+ params = group.generateLayoutParams(attrs);
+ } catch (RuntimeException e) {
+ // Ignore, just fail over to child attrs.
+ }
+ if (params == null) {
+ params = group.generateLayoutParams(childAttrs);
+ }
+ view.setLayoutParams(params);
+
+ // Inflate all children.
+ rInflateChildren(childParser, view, childAttrs, true);
+
+ if (id != View.NO_ID) {
+ view.setId(id);
+ }
+
+ switch (visibility) {
+ case 0:
+ view.setVisibility(View.VISIBLE);
+ break;
+ case 1:
+ view.setVisibility(View.INVISIBLE);
+ break;
+ case 2:
+ view.setVisibility(View.GONE);
+ break;
+ }
+
+ group.addView(view);
+ }
+ } finally {
+ childParser.close();
+ }
+
LayoutInflater.consumeChildElements(parser);
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index ea6f2fe..92e0187 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -258,14 +258,27 @@
}
mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
}
- mEvents.add(event);
+
+ if (!mEvents.isEmpty() && event.getType() == TYPE_VIEW_TEXT_CHANGED) {
+ final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
+
+ // TODO(b/121045053): check if flags match
+ if (lastEvent.getType() == TYPE_VIEW_TEXT_CHANGED
+ && lastEvent.getId().equals(event.getId())) {
+ if (VERBOSE) {
+ Log.v(mTag, "Buffering VIEW_TEXT_CHANGED event, updated text = "
+ + event.getText());
+ }
+ lastEvent.setText(event.getText());
+ } else {
+ mEvents.add(event);
+ }
+ } else {
+ mEvents.add(event);
+ }
final int numberEvents = mEvents.size();
- // TODO(b/120784831): need to optimize it so we buffer changes until a number of X are
- // buffered (either total or per autofillid). For
- // example, if the user typed "a", "b", "c" and the threshold is 3, we should buffer
- // "a" and "b" then send "abc".
final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE;
if (bufferEvent && !forceFlush) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 414cb8f..bad2dbf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -850,7 +850,7 @@
/**
* Asynchronously evaluates JavaScript in the context of the currently displayed page.
- * If non-null, |resultCallback| will be invoked with any result returned from that
+ * If non-null, {@code resultCallback} will be invoked with any result returned from that
* execution. This method must be called on the UI thread and the callback will
* be made on the UI thread.
* <p>
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 6ab7f66..ef69b63 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -138,6 +138,20 @@
}
/**
+ * Call webview draw functor. See API in draw_fn.h.
+ * @param canvas a hardware accelerated canvas (see {@link Canvas#isHardwareAccelerated()}).
+ * @param functor created by AwDrawFn_CreateFunctor in draw_fn.h.
+ */
+ public void drawWebViewFunctor(@NonNull Canvas canvas, int functor) {
+ if (!(canvas instanceof RecordingCanvas)) {
+ // Canvas#isHardwareAccelerated() is only true for subclasses of RecordingCanvas.
+ throw new IllegalArgumentException(canvas.getClass().getName()
+ + " is not a RecordingCanvas canvas");
+ }
+ ((RecordingCanvas) canvas).drawWebViewFunctor(functor);
+ }
+
+ /**
* Detaches the draw GL functor.
*
* @param nativeDrawGLFunctor the pointer to the native functor that implements
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 78d366c..2995a8f 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -16,14 +16,14 @@
package com.android.internal.hardware;
-import com.android.internal.R;
-
import android.content.Context;
import android.os.Build;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.TextUtils;
+import com.android.internal.R;
+
public class AmbientDisplayConfiguration {
private final Context mContext;
@@ -37,7 +37,8 @@
public boolean enabled(int user) {
return pulseOnNotificationEnabled(user)
|| pulseOnLongPressEnabled(user)
- || alwaysOnEnabled(user);
+ || alwaysOnEnabled(user)
+ || wakeLockScreenGestureEnabled(user);
}
public boolean pulseOnNotificationEnabled(int user) {
diff --git a/core/jni/android/graphics/text/LineBreaker.cpp b/core/jni/android/graphics/text/LineBreaker.cpp
index e1f2f2b..c23f1e9 100644
--- a/core/jni/android/graphics/text/LineBreaker.cpp
+++ b/core/jni/android/graphics/text/LineBreaker.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "LineBreaker"
-#include "unicode/locid.h"
-#include "unicode/brkiter.h"
#include "utils/misc.h"
#include "utils/Log.h"
#include <nativehelper/ScopedStringChars.h>
diff --git a/core/jni/android/graphics/text/MeasuredText.cpp b/core/jni/android/graphics/text/MeasuredText.cpp
index d7d96fb..68ba38b 100644
--- a/core/jni/android/graphics/text/MeasuredText.cpp
+++ b/core/jni/android/graphics/text/MeasuredText.cpp
@@ -17,8 +17,6 @@
#define LOG_TAG "MeasuredText"
#include "GraphicsJNI.h"
-#include "unicode/locid.h"
-#include "unicode/brkiter.h"
#include "utils/misc.h"
#include "utils/Log.h"
#include <nativehelper/ScopedStringChars.h>
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 29d8f30..80560f8 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1906,6 +1906,53 @@
return jStatus;
}
+static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobject clazz,
+ jint uid, jintArray deviceTypes, jobjectArray deviceAddresses) {
+ if (deviceTypes == nullptr || deviceAddresses == nullptr) {
+ return (jint) AUDIO_JAVA_BAD_VALUE;
+ }
+ jsize nb = env->GetArrayLength(deviceTypes);
+ if (nb == 0 || nb != env->GetArrayLength(deviceAddresses)) {
+ return (jint) AUDIO_JAVA_BAD_VALUE;
+ }
+ // retrieve all device types
+ std::vector<audio_devices_t> deviceTypesVector;
+ jint* typesPtr = nullptr;
+ typesPtr = env->GetIntArrayElements(deviceTypes, 0);
+ if (typesPtr == nullptr) {
+ return (jint) AUDIO_JAVA_BAD_VALUE;
+ }
+ for (jint i = 0; i < nb; i++) {
+ deviceTypesVector.push_back((audio_devices_t) typesPtr[i]);
+ }
+ env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
+
+ // check each address is a string and add device type/address to list for device affinity
+ Vector<AudioDeviceTypeAddr> deviceVector;
+ jclass stringClass = FindClassOrDie(env, "java/lang/String");
+ for (jint i = 0; i < nb; i++) {
+ jobject addrJobj = env->GetObjectArrayElement(deviceAddresses, i);
+ if (!env->IsInstanceOf(addrJobj, stringClass)) {
+ return (jint) AUDIO_JAVA_BAD_VALUE;
+ }
+ String8 address = String8(env->GetStringUTFChars((jstring) addrJobj, NULL));
+ AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
+ deviceVector.add(dev);
+ }
+
+ status_t status = AudioSystem::setUidDeviceAffinities((uid_t) uid, deviceVector);
+ return (jint) nativeToJavaStatus(status);
+}
+
+static jint android_media_AudioSystem_removeUidDeviceAffinities(JNIEnv *env, jobject clazz,
+ jint uid) {
+
+ //###
+ status_t status = NO_ERROR;//AudioSystem::removeUidDeviceAffinities();
+ return (jint) nativeToJavaStatus(status);
+}
+
+
static jint
android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
{
@@ -2133,6 +2180,10 @@
(void *)android_media_AudioSystem_getAudioHwSyncForSession},
{"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
(void *)android_media_AudioSystem_registerPolicyMixes},
+ {"setUidDeviceAffinities", "(I[I[Ljava/lang/String;)I",
+ (void *)android_media_AudioSystem_setUidDeviceAffinities},
+ {"removeUidDeviceAffinities", "(I)I",
+ (void *)android_media_AudioSystem_removeUidDeviceAffinities},
{"native_register_dynamic_policy_callback", "()V",
(void *)android_media_AudioSystem_registerDynPolicyCallback},
{"native_register_recording_callback", "()V",
diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto
index db4a4c4..c357065 100644
--- a/core/proto/android/os/enums.proto
+++ b/core/proto/android/os/enums.proto
@@ -57,6 +57,7 @@
}
// These constants are defined in hardware/interfaces/thermal/1.0/types.hal
+// and in hardware/interfaces/thermal/2.0/types.hal
// They are primarily used by android/os/HardwarePropertiesManager.java.
// Any change to the types in the thermal hal should be made here as well.
enum TemperatureTypeEnum {
@@ -65,6 +66,16 @@
TEMPERATURE_TYPE_GPU = 1;
TEMPERATURE_TYPE_BATTERY = 2;
TEMPERATURE_TYPE_SKIN = 3;
+ TEMPERATURE_TYPE_USB_PORT = 4;
+ TEMPERATURE_TYPE_POWER_AMPLIFIER = 5;
+
+ // Battery Charge Limit - virtual thermal sensors.
+ TEMPERATURE_TYPE_BCL_VOLTAGE = 6;
+ TEMPERATURE_TYPE_BCL_CURRENT = 7;
+ TEMPERATURE_TYPE_BCL_PERCENTAGE = 8;
+
+ // Neural Processing Unit.
+ TEMPERATURE_TYPE_NPU = 9;
}
// Wakelock types, primarily used by android/os/PowerManager.java.
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 11bd43b..a914369 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -436,9 +436,11 @@
// Ordered GPU debug layer list for GLES
// i.e. <layer1>:<layer2>:...:<layerN>
optional SettingProto debug_layers_gles = 7;
- // App opt in to load updated graphics driver instead of
- // native graphcis driver through developer options.
- optional SettingProto updated_gfx_driver_dev_opt_in_app = 8;
+ // Apps opt in to load graphics driver from Game Update Package
+ // instead of native graphcis driver through developer options.
+ optional SettingProto gup_dev_opt_in_apps = 8;
+ // Apps on the black list that are forbidden to useGame Update Package.
+ optional SettingProto gup_black_list = 9;
}
optional Gpu gpu = 59;
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 60561bd..6f9a564 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -82,6 +82,7 @@
repeated ActivityStackProto stacks = 3;
optional int32 focused_stack_id = 4;
optional .com.android.server.wm.IdentifierProto resumed_activity = 5;
+ optional bool single_task_instance = 6;
}
message ActivityStackProto {
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index dd51cb6..54f6c63 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1112,6 +1112,11 @@
resource] to be present in order to function. Default value is false. -->
<attr name="isSplitRequired" format="boolean" />
+ <!-- Flag to specify if this app prioritizes code integrity. The system may choose
+ to run with better integrity guarantee in various components if possible based on the app's
+ <code>targetSdkVersion</code>. -->
+ <attr name="preferCodeIntegrity" format="boolean" />
+
<!-- Extra options for an activity's UI. Applies to either the {@code <activity>} or
{@code <application>} tag. If specified on the {@code <application>}
tag these will be considered defaults for all activities in the
@@ -1580,6 +1585,7 @@
to honor this flag as well. -->
<attr name="usesCleartextTraffic" />
<attr name="multiArch" />
+ <attr name="preferCodeIntegrity" />
<attr name="extractNativeLibs" />
<attr name="defaultToDeviceProtectedStorage" format="boolean" />
<attr name="directBootAware" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 11cc1f5..e4abf8f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -929,6 +929,9 @@
in hardware. -->
<bool name="config_setColorTransformAccelerated">false</bool>
+ <!-- Boolean indicating whether display white balance is supported. -->
+ <bool name="config_displayWhiteBalanceAvailable">false</bool>
+
<!-- Control whether Night display is available. This should only be enabled on devices
that have a HWC implementation that can apply the matrix passed to setColorTransform
without impacting power, performance, and app compatibility (e.g. protected content). -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d383362..2b95dd0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3072,7 +3072,7 @@
<!-- Title of intent resolver dialog when selecting a viewer application that opens URI
and a previously used application is known [CHAR LIMIT=128]. -->
<string name="whichGiveAccessToApplicationNamed">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Gmail">%2$s</xliff:g></string>
- <!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=16] -->
+ <!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=18] -->
<string name="whichGiveAccessToApplicationLabel">Give access</string>
<!-- Title of intent resolver dialog when selecting an editor application to run. -->
<string name="whichEditApplication">Edit with</string>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 7c95d1e..200ef2f 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -355,6 +355,30 @@
<item name="fontFamily">@string/config_bodyFontFamilyMedium</item>
</style>
<style name="TextAppearance.DeviceDefault.Widget.Toolbar.Title" parent="TextAppearance.DeviceDefault.Widget.ActionBar.Title"/>
+ <style name="TextAppearance.DeviceDefault.Widget.Toolbar.Subtitle" parent="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle"/>
+ <style name="TextAppearance.DeviceDefault.Body1" parent="TextAppearance.Material.Body1">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Body2" parent="TextAppearance.Material.Body2">
+ <item name="fontFamily">@string/config_bodyFontFamilyMedium</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Subhead" parent="TextAppearance.Material.Subhead">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Headline" parent="TextAppearance.Material.Headline">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Display1" parent="TextAppearance.Material.Display1">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Title" parent="TextAppearance.Material.Title">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.Caption" parent="TextAppearance.Material.Caption">
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
+ </style>
+ <style name="TextAppearance.DeviceDefault.ListItem" parent="TextAppearance.DeviceDefault.Subhead"/>
+ <style name="TextAppearance.DeviceDefault.ListItemSecondary" parent="TextAppearance.DeviceDefault.Body1"/>
<!-- Preference Styles -->
<style name="Preference.DeviceDefault" parent="Preference.Material"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eda25b3..e8cbf66 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3028,6 +3028,7 @@
<java-symbol type="drawable" name="ic_doc_generic" />
<java-symbol type="bool" name="config_setColorTransformAccelerated" />
+ <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
<java-symbol type="bool" name="config_nightDisplayAvailable" />
<java-symbol type="bool" name="config_allowDisablingAssistDisclosure" />
<java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 56265cc..0f4ca66 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -68,6 +68,10 @@
<item name="textAppearanceLargePopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
<item name="textAppearanceSmallPopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
+ <item name="textAppearanceListItem">@style/TextAppearance.DeviceDefault.ListItem</item>
+ <item name="textAppearanceListItemSmall">@style/TextAppearance.DeviceDefault.ListItem</item>
+ <item name="textAppearanceListItemSecondary">@style/TextAppearance.DeviceDefault.ListItemSecondary</item>
+
<!-- Button styles -->
<item name="buttonCornerRadius">@dimen/config_buttonCornerRadius</item>
<item name="buttonStyle">@style/Widget.DeviceDefault.Button</item>
@@ -783,7 +787,6 @@
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
<item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
-
<item name="textAppearanceLarge">@style/TextAppearance.DeviceDefault.Large</item>
<item name="textAppearanceMedium">@style/TextAppearance.DeviceDefault.Medium</item>
<item name="textAppearanceSmall">@style/TextAppearance.DeviceDefault.Small</item>
@@ -792,11 +795,12 @@
<item name="textAppearanceSmallInverse">@style/TextAppearance.DeviceDefault.Small.Inverse</item>
<item name="textAppearanceSearchResultTitle">@style/TextAppearance.DeviceDefault.SearchResult.Title</item>
<item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.DeviceDefault.SearchResult.Subtitle</item>
-
<item name="textAppearanceButton">@style/TextAppearance.DeviceDefault.Widget.Button</item>
-
<item name="textAppearanceLargePopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Large</item>
<item name="textAppearanceSmallPopupMenu">@style/TextAppearance.DeviceDefault.Widget.PopupMenu.Small</item>
+ <item name="textAppearanceListItem">@style/TextAppearance.DeviceDefault.ListItem</item>
+ <item name="textAppearanceListItemSmall">@style/TextAppearance.DeviceDefault.ListItem</item>
+ <item name="textAppearanceListItemSecondary">@style/TextAppearance.DeviceDefault.ListItemSecondary</item>
<!-- Button styles -->
<item name="buttonCornerRadius">@dimen/config_buttonCornerRadius</item>
@@ -1439,19 +1443,23 @@
</style>
<!-- DeviceDefault theme for a window that should look like the Settings app. -->
- <style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings">
+ <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault.Light">
+ <!-- From Theme.Material.Light.LightStatusBar -->
+ <item name="windowLightStatusBar">true</item>
+
+ <!-- From Theme.Material.Settings -->
+ <item name="homeAsUpIndicator">@drawable/ic_ab_back_material_settings</item>
+ <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
+ <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
+ <item name="panelMenuListTheme">@style/Theme.Material.Settings.CompactMenu</item>
+
<!-- action bar -->
- <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar.Solid</item>
<item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar</item>
<item name="popupTheme">@style/ThemeOverlay.DeviceDefault.Popup.Light</item>
<!-- Color palette -->
- <item name="colorBackground">@color/background_device_default_light</item>
- <item name="colorPrimary">@color/primary_device_default_settings_light</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
- <item name="colorAccent">@color/accent_device_default_light</item>
- <item name="colorError">@color/error_color_device_default_light</item>
<item name="colorEdgeEffect">@android:color/black</item>
<!-- Add white nav bar with divider that matches material -->
@@ -1459,24 +1467,9 @@
<item name="navigationBarColor">@android:color/white</item>
<item name="windowLightNavigationBar">true</item>
- <!-- Dialog attributes -->
- <item name="dialogCornerRadius">@dimen/config_dialogCornerRadius</item>
- <item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
-
- <!-- Text styles -->
- <item name="textAppearanceButton">@style/TextAppearance.DeviceDefault.Widget.Button</item>
-
<!-- Button styles -->
- <item name="buttonCornerRadius">@dimen/config_buttonCornerRadius</item>
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
- <!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
- <item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
-
- <!-- Toolbar attributes -->
- <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
-
<item name="listDivider">@color/list_divider_color_light</item>
</style>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index f8bd4e3..ac57d20 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -475,7 +475,8 @@
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
- Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
+ Settings.Global.GUP_DEV_OPT_IN_APPS,
+ Settings.Global.GUP_BLACK_LIST,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 7e69e3a..96798f9 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -61,6 +61,7 @@
"libstatslog",
"libutils",
"libEGL",
+ "libGLESv1_CM",
"libGLESv2",
"libGLESv3",
"libvulkan",
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index bd1e6c5..14e3a32 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -41,14 +41,10 @@
X(DrawImageNine)
X(DrawImageRect)
X(DrawImageLattice)
-X(DrawText)
-X(DrawPosText)
-X(DrawPosTextH)
-X(DrawTextRSXform)
X(DrawTextBlob)
X(DrawPatch)
X(DrawPoints)
X(DrawVertices)
X(DrawAtlas)
X(DrawShadowRec)
-X(DrawVectorDrawable)
\ No newline at end of file
+X(DrawVectorDrawable)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 4de25f9..6dc9d34 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -373,61 +373,6 @@
}
};
-struct DrawText final : Op {
- static const auto kType = Type::DrawText;
- DrawText(size_t bytes, SkScalar x, SkScalar y, const SkPaint& paint)
- : bytes(bytes), x(x), y(y), paint(paint) {}
- size_t bytes;
- SkScalar x, y;
- SkPaint paint;
- void draw(SkCanvas* c, const SkMatrix&) const {
- c->drawText(pod<void>(this), bytes, x, y, paint);
- }
-};
-struct DrawPosText final : Op {
- static const auto kType = Type::DrawPosText;
- DrawPosText(size_t bytes, const SkPaint& paint, int n) : bytes(bytes), paint(paint), n(n) {}
- size_t bytes;
- SkPaint paint;
- int n;
- void draw(SkCanvas* c, const SkMatrix&) const {
- auto points = pod<SkPoint>(this);
- auto text = pod<void>(this, n * sizeof(SkPoint));
- c->drawPosText(text, bytes, points, paint);
- }
-};
-struct DrawPosTextH final : Op {
- static const auto kType = Type::DrawPosTextH;
- DrawPosTextH(size_t bytes, SkScalar y, const SkPaint& paint, int n)
- : bytes(bytes), y(y), paint(paint), n(n) {}
- size_t bytes;
- SkScalar y;
- SkPaint paint;
- int n;
- void draw(SkCanvas* c, const SkMatrix&) const {
- auto xs = pod<SkScalar>(this);
- auto text = pod<void>(this, n * sizeof(SkScalar));
- c->drawPosTextH(text, bytes, xs, y, paint);
- }
-};
-struct DrawTextRSXform final : Op {
- static const auto kType = Type::DrawTextRSXform;
- DrawTextRSXform(size_t bytes, int xforms, const SkRect* cull, const SkPaint& paint)
- : bytes(bytes), xforms(xforms), paint(paint) {
- if (cull) {
- this->cull = *cull;
- }
- }
- size_t bytes;
- int xforms;
- SkRect cull = kUnset;
- SkPaint paint;
- void draw(SkCanvas* c, const SkMatrix&) const {
- // For alignment, the SkRSXforms are first in the pod section, followed by the text.
- c->drawTextRSXform(pod<void>(this, xforms * sizeof(SkRSXform)), bytes, pod<SkRSXform>(this),
- maybe_unset(cull), paint);
- }
-};
struct DrawTextBlob final : Op {
static const auto kType = Type::DrawTextBlob;
DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
@@ -682,33 +627,6 @@
fs);
}
-void DisplayListData::drawText(const void* text, size_t bytes, SkScalar x, SkScalar y,
- const SkPaint& paint) {
- void* pod = this->push<DrawText>(bytes, bytes, x, y, paint);
- copy_v(pod, (const char*)text, bytes);
- mHasText = true;
-}
-void DisplayListData::drawPosText(const void* text, size_t bytes, const SkPoint pos[],
- const SkPaint& paint) {
- int n = paint.countText(text, bytes);
- void* pod = this->push<DrawPosText>(n * sizeof(SkPoint) + bytes, bytes, paint, n);
- copy_v(pod, pos, n, (const char*)text, bytes);
- mHasText = true;
-}
-void DisplayListData::drawPosTextH(const void* text, size_t bytes, const SkScalar xs[], SkScalar y,
- const SkPaint& paint) {
- int n = paint.countText(text, bytes);
- void* pod = this->push<DrawPosTextH>(n * sizeof(SkScalar) + bytes, bytes, y, paint, n);
- copy_v(pod, xs, n, (const char*)text, bytes);
- mHasText = true;
-}
-void DisplayListData::drawTextRSXform(const void* text, size_t bytes, const SkRSXform xforms[],
- const SkRect* cull, const SkPaint& paint) {
- int n = paint.countText(text, bytes);
- void* pod = this->push<DrawTextRSXform>(bytes + n * sizeof(SkRSXform), bytes, n, cull, paint);
- copy_v(pod, xforms, n, (const char*)text, bytes);
- mHasText = true;
-}
void DisplayListData::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
this->push<DrawTextBlob>(0, blob, x, y, paint);
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index ae3c4f05..caaef67 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -101,10 +101,6 @@
void drawDrawable(SkDrawable*, const SkMatrix*);
void drawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
- void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&);
- void drawPosText(const void*, size_t, const SkPoint[], const SkPaint&);
- void drawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&);
- void drawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*, const SkPaint&);
void drawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&);
void drawImage(sk_sp<const SkImage>, SkScalar, SkScalar, const SkPaint*, BitmapPalette palette);
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 20e77b4..5b7ae70 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -37,7 +37,8 @@
}
}
-int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode) {
+int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype,
+ RenderMode functorMode) {
if (functorMode != RenderMode::OpenGL_ES && functorMode != RenderMode::Vulkan) {
ALOGW("Unknown rendermode %d", (int)functorMode);
return -1;
@@ -47,7 +48,7 @@
ALOGW("Unable to map from GLES platform to a vulkan functor");
return -1;
}
- return WebViewFunctorManager::instance().createFunctor(prototype, functorMode);
+ return WebViewFunctorManager::instance().createFunctor(data, prototype, functorMode);
}
void WebViewFunctor_release(int functor) {
@@ -56,7 +57,9 @@
static std::atomic_int sNextId{1};
-WebViewFunctor::WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode) {
+WebViewFunctor::WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
+ RenderMode functorMode)
+ : mData(data) {
mFunctor = sNextId++;
mCallbacks = callbacks;
mMode = functorMode;
@@ -66,12 +69,12 @@
destroyContext();
ATRACE_NAME("WebViewFunctor::onDestroy");
- mCallbacks.onDestroyed(mFunctor);
+ mCallbacks.onDestroyed(mFunctor, mData);
}
void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
ATRACE_NAME("WebViewFunctor::sync");
- mCallbacks.onSync(mFunctor, syncData);
+ mCallbacks.onSync(mFunctor, mData, syncData);
}
void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
@@ -79,14 +82,14 @@
if (!mHasContext) {
mHasContext = true;
}
- mCallbacks.gles.draw(mFunctor, drawInfo);
+ mCallbacks.gles.draw(mFunctor, mData, drawInfo);
}
void WebViewFunctor::destroyContext() {
if (mHasContext) {
mHasContext = false;
ATRACE_NAME("WebViewFunctor::onContextDestroyed");
- mCallbacks.onContextDestroyed(mFunctor);
+ mCallbacks.onContextDestroyed(mFunctor, mData);
}
}
@@ -95,9 +98,9 @@
return sInstance;
}
-int WebViewFunctorManager::createFunctor(const WebViewFunctorCallbacks& callbacks,
+int WebViewFunctorManager::createFunctor(void* data, const WebViewFunctorCallbacks& callbacks,
RenderMode functorMode) {
- auto object = std::make_unique<WebViewFunctor>(callbacks, functorMode);
+ auto object = std::make_unique<WebViewFunctor>(data, callbacks, functorMode);
int id = object->id();
auto handle = object->createHandle();
{
@@ -164,4 +167,4 @@
return nullptr;
}
-} // namespace android::uirenderer
\ No newline at end of file
+} // namespace android::uirenderer
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 2a621dd..1719ce7 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -29,7 +29,7 @@
class WebViewFunctor {
public:
- WebViewFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
+ WebViewFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
~WebViewFunctor();
class Handle : public LightRefBase<Handle> {
@@ -63,6 +63,7 @@
private:
WebViewFunctorCallbacks mCallbacks;
+ void* const mData;
int mFunctor;
RenderMode mMode;
bool mHasContext = false;
@@ -73,7 +74,7 @@
public:
static WebViewFunctorManager& instance();
- int createFunctor(const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
+ int createFunctor(void* data, const WebViewFunctorCallbacks& callbacks, RenderMode functorMode);
void releaseFunctor(int functor);
void onContextDestroyed();
void destroyFunctor(int functor);
diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h
index e5346aa..da3d06a 100644
--- a/libs/hwui/private/hwui/WebViewFunctor.h
+++ b/libs/hwui/private/hwui/WebViewFunctor.h
@@ -17,6 +17,7 @@
#ifndef FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H
#define FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H
+#include <cutils/compiler.h>
#include <private/hwui/DrawGlInfo.h>
namespace android::uirenderer {
@@ -27,7 +28,7 @@
};
// Static for the lifetime of the process
-RenderMode WebViewFunctor_queryPlatformRenderMode();
+ANDROID_API RenderMode WebViewFunctor_queryPlatformRenderMode();
struct WebViewSyncData {
bool applyForceDark;
@@ -35,21 +36,21 @@
struct WebViewFunctorCallbacks {
// kModeSync, called on RenderThread
- void (*onSync)(int functor, const WebViewSyncData& syncData);
+ void (*onSync)(int functor, void* data, const WebViewSyncData& syncData);
// Called when either the context is destroyed _or_ when the functor's last reference goes
// away. Will always be called with an active context and always on renderthread.
- void (*onContextDestroyed)(int functor);
+ void (*onContextDestroyed)(int functor, void* data);
// Called when the last reference to the handle goes away and the handle is considered
// irrevocably destroyed. Will always be proceeded by a call to onContextDestroyed if
// this functor had ever been drawn.
- void (*onDestroyed)(int functor);
+ void (*onDestroyed)(int functor, void* data);
union {
struct {
// Called on RenderThread. initialize is guaranteed to happen before this call
- void (*draw)(int functor, const DrawGlInfo& params);
+ void (*draw)(int functor, void* data, const DrawGlInfo& params);
} gles;
// TODO: VK support. The current DrawVkInfo is monolithic and needs to be split up for
// what params are valid on what callbacks
@@ -70,12 +71,12 @@
// Creates a new WebViewFunctor from the given prototype. The prototype is copied after
// this function returns. Caller retains full ownership of it.
// Returns -1 if the creation fails (such as an unsupported functorMode + platform mode combination)
-int WebViewFunctor_create(const WebViewFunctorCallbacks& prototype, RenderMode functorMode);
+ANDROID_API int WebViewFunctor_create(void* data, const WebViewFunctorCallbacks& prototype, RenderMode functorMode);
// May be called on any thread to signal that the functor should be destroyed.
// The functor will receive an onDestroyed when the last usage of it is released,
// and it should be considered alive & active until that point.
-void WebViewFunctor_release(int functor);
+ANDROID_API void WebViewFunctor_release(int functor);
} // namespace android::uirenderer
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 5ff8993..6a1ca5a 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -315,24 +315,24 @@
static WebViewFunctorCallbacks createMockFunctor(RenderMode mode) {
auto callbacks = WebViewFunctorCallbacks{
.onSync =
- [](int functor, const WebViewSyncData& data) {
+ [](int functor, void* client_data, const WebViewSyncData& data) {
expectOnRenderThread();
sMockFunctorCounts[functor].sync++;
},
.onContextDestroyed =
- [](int functor) {
+ [](int functor, void* client_data) {
expectOnRenderThread();
sMockFunctorCounts[functor].contextDestroyed++;
},
.onDestroyed =
- [](int functor) {
+ [](int functor, void* client_data) {
expectOnRenderThread();
sMockFunctorCounts[functor].destroyed++;
},
};
switch (mode) {
case RenderMode::OpenGL_ES:
- callbacks.gles.draw = [](int functor, const DrawGlInfo& params) {
+ callbacks.gles.draw = [](int functor, void* client_data, const DrawGlInfo& params) {
expectOnRenderThread();
sMockFunctorCounts[functor].glesDraw++;
};
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index 9a1ee54..4111bd2 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -16,7 +16,7 @@
#include "TestSceneBase.h"
#include "tests/common/TestListViewSceneBase.h"
-
+#include <SkFont.h>
#include <cstdio>
class ListViewAnimation;
@@ -46,11 +46,13 @@
SkColorGetR(randomColor) + SkColorGetG(randomColor) + SkColorGetB(randomColor) <
128 * 3;
paint.setColor(bgDark ? Color::White : Color::Grey_700);
- paint.setTextSize(size / 2);
+
+ SkFont font;
+ font.setSize(size / 2);
char charToShow = 'A' + (rand() % 26);
- const SkPoint pos[] = {{SkIntToScalar(size / 2),
- /*approximate centering*/ SkFloatToScalar(size * 0.7f)}};
- canvas.drawPosText(&charToShow, 1, pos, paint);
+ const SkPoint pos = {SkIntToScalar(size / 2),
+ /*approximate centering*/ SkFloatToScalar(size * 0.7f)};
+ canvas.drawSimpleText(&charToShow, 1, kUTF8_SkTextEncoding, pos.fX, pos.fY, font, paint);
return bitmap;
}
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 53bf84f..1b4cf7e 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -100,8 +100,8 @@
GLFunctorDrawable functorDrawable(&functor, nullptr, &dummyCanvas);
skiaDL.mChildFunctors.push_back(&functorDrawable);
- int functor2 = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor2 = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
auto& counts = TestUtils::countsForFunctor(functor2);
skiaDL.mChildFunctors.push_back(
skiaDL.allocateDrawable<GLFunctorDrawable>(functor2, &dummyCanvas));
diff --git a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
index c8169af..e1fb8b7 100644
--- a/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
+++ b/libs/hwui/tests/unit/WebViewFunctorManagerTests.cpp
@@ -27,8 +27,8 @@
using namespace android::uirenderer;
TEST(WebViewFunctor, createDestroyGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
WebViewFunctor_release(functor);
TestUtils::runOnRenderThreadUnmanaged([](renderthread::RenderThread&) {
@@ -41,8 +41,8 @@
}
TEST(WebViewFunctor, createSyncHandleGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -82,8 +82,8 @@
}
TEST(WebViewFunctor, createSyncDrawGLES) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -109,8 +109,8 @@
}
TEST(WebViewFunctor, contextDestroyed) {
- int functor = WebViewFunctor_create(TestUtils::createMockFunctor(RenderMode::OpenGL_ES),
- RenderMode::OpenGL_ES);
+ int functor = WebViewFunctor_create(
+ nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
ASSERT_NE(-1, functor);
auto handle = WebViewFunctorManager::instance().handleFor(functor);
ASSERT_TRUE(handle);
@@ -151,4 +151,4 @@
EXPECT_EQ(2, counts.glesDraw);
EXPECT_EQ(2, counts.contextDestroyed);
EXPECT_EQ(1, counts.destroyed);
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 63eefe0..30b5480 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4280,9 +4280,8 @@
* Return codes for listAudioPorts(), createAudioPatch() ...
*/
- /** @hide
- * CANDIDATE FOR PUBLIC API
- */
+ /** @hide */
+ @SystemApi
public static final int SUCCESS = AudioSystem.SUCCESS;
/**
* A default error code.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 58fc1ab..45cde0f 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -916,6 +916,13 @@
public static native int registerPolicyMixes(ArrayList<AudioMix> mixes, boolean register);
+ /** see AudioPolicy.setUidDeviceAffinities() */
+ public static native int setUidDeviceAffinities(int uid, @NonNull int[] types,
+ @NonNull String[] addresses);
+
+ /** see AudioPolicy.removeUidDeviceAffinities() */
+ public static native int removeUidDeviceAffinities(int uid);
+
public static native int systemReady();
public static native float getStreamVolumeDB(int stream, int index, int device);
diff --git a/media/java/android/media/Controller2Link.java b/media/java/android/media/Controller2Link.java
index 2601ff7..a62db5f 100644
--- a/media/java/android/media/Controller2Link.java
+++ b/media/java/android/media/Controller2Link.java
@@ -25,8 +25,7 @@
import java.util.Objects;
/**
- * Handles incoming commands from {@link MediaSession2} and {@link MediaLibrarySession}
- * to both {@link MediaController2} and {@link MediaBrowser2}.
+ * Handles incoming commands from {@link MediaSession2} to both {@link MediaController2}.
* @hide
*/
// @SystemApi
@@ -90,7 +89,7 @@
try {
mIController.notifyConnected(seq, connectionResult);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
}
}
@@ -99,7 +98,7 @@
try {
mIController.notifyDisconnected(seq);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
}
}
@@ -109,7 +108,16 @@
try {
mIController.sendSessionCommand(seq, command, args, resultReceiver);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Interface method for IMediaController2.cancelSessionCommand */
+ public void cancelSessionCommand(int seq) {
+ try {
+ mIController.cancelSessionCommand(seq);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
}
}
@@ -133,6 +141,11 @@
mController.onSessionCommand(seq, command, args, resultReceiver);
}
+ /** Stub implementation for IMediaController2.cancelSessionCommand */
+ public void onCancelCommand(int seq) {
+ mController.onCancelCommand(seq);
+ }
+
private class Controller2Stub extends IMediaController2.Stub {
@Override
public void notifyConnected(int seq, Bundle connectionResult) {
@@ -149,5 +162,10 @@
ResultReceiver resultReceiver) {
Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver);
}
+
+ @Override
+ public void cancelSessionCommand(int seq) {
+ Controller2Link.this.onCancelCommand(seq);
+ }
}
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index abd6411..9fbd7ea 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -223,6 +223,11 @@
boolean isAudioServerRunning();
+ int setUidDeviceAffinity(in IAudioPolicyCallback pcb, in int uid, in int[] deviceTypes,
+ in String[] deviceAddresses);
+
+ int removeUidDeviceAffinity(in IAudioPolicyCallback pcb, in int uid);
+
// WARNING: read warning at top of file, new methods that need to be used by native
// code via IAudioManager.h need to be added to the top section.
}
diff --git a/media/java/android/media/IMediaController2.aidl b/media/java/android/media/IMediaController2.aidl
index df34a11..ca5394f 100644
--- a/media/java/android/media/IMediaController2.aidl
+++ b/media/java/android/media/IMediaController2.aidl
@@ -33,4 +33,6 @@
void notifyDisconnected(int seq) = 1;
void sendSessionCommand(int seq, in Session2Command command, in Bundle args,
in ResultReceiver resultReceiver) = 2;
+ void cancelSessionCommand(int seq) = 3;
+ // Next Id : 4
}
diff --git a/media/java/android/media/IMediaSession2.aidl b/media/java/android/media/IMediaSession2.aidl
index f6e74cf..26e717b 100644
--- a/media/java/android/media/IMediaSession2.aidl
+++ b/media/java/android/media/IMediaSession2.aidl
@@ -34,5 +34,6 @@
void disconnect(in Controller2Link caller, int seq) = 1;
void sendSessionCommand(in Controller2Link caller, int seq, in Session2Command sessionCommand,
in Bundle args, in ResultReceiver resultReceiver) = 2;
- // Next Id : 3
+ void cancelSessionCommand(in Controller2Link caller, int seq) = 3;
+ // Next Id : 4
}
diff --git a/media/java/android/media/MediaConstants.java b/media/java/android/media/MediaConstants.java
index ffdca16d8..275b0ac 100644
--- a/media/java/android/media/MediaConstants.java
+++ b/media/java/android/media/MediaConstants.java
@@ -16,7 +16,6 @@
package android.media;
-// Code for AML only
class MediaConstants {
// Bundle key for int
static final String KEY_PID = "android.media.key.PID";
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 4ef56c8..7665c92 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -20,6 +20,8 @@
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;
import static android.media.MediaConstants.KEY_SESSION2_STUB;
+import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
+import static android.media.Session2Command.RESULT_INFO_SKIPPED;
import static android.media.Session2Token.TYPE_SESSION;
import android.annotation.NonNull;
@@ -31,6 +33,8 @@
import android.os.IBinder;
import android.os.Process;
import android.os.ResultReceiver;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import java.util.concurrent.Executor;
@@ -69,6 +73,21 @@
private Session2CommandGroup mAllowedCommands;
//@GuardedBy("mLock")
private Session2Token mConnectedToken;
+ //@GuardedBy("mLock")
+ private ArrayMap<ResultReceiver, Integer> mPendingCommands;
+ //@GuardedBy("mLock")
+ private ArraySet<Integer> mRequestedCommandSeqNumbers;
+
+ /**
+ * Create a {@link MediaController2} from the {@link Session2Token}.
+ * This connects to the session and may wake up the service if it's not available.
+ *
+ * @param context Context
+ * @param token token to connect to
+ */
+ public MediaController2(@NonNull Context context, @NonNull Session2Token token) {
+ this(context, token, context.getMainExecutor(), new ControllerCallback() {});
+ }
/**
* Create a {@link MediaController2} from the {@link Session2Token}.
@@ -77,31 +96,27 @@
* @param context Context
* @param token token to connect to
* @param executor executor to run callbacks on.
- * @param callback controller callback to receive changes in
+ * @param callback controller callback to receive changes in.
*/
- public MediaController2(@NonNull final Context context, @NonNull final Session2Token token,
- @NonNull final Executor executor, @NonNull final ControllerCallback callback) {
+ public MediaController2(@NonNull Context context, @NonNull Session2Token token,
+ @NonNull Executor executor, @NonNull ControllerCallback callback) {
if (context == null) {
throw new IllegalArgumentException("context shouldn't be null");
}
if (token == null) {
throw new IllegalArgumentException("token shouldn't be null");
}
- if (callback == null) {
- throw new IllegalArgumentException("callback shouldn't be null");
- }
- if (executor == null) {
- throw new IllegalArgumentException("executor shouldn't be null");
- }
mContext = context;
mSessionToken = token;
- mCallbackExecutor = executor;
- mCallback = callback;
+ mCallbackExecutor = (executor == null) ? context.getMainExecutor() : executor;
+ mCallback = (callback == null) ? new ControllerCallback() { } : callback;
mControllerStub = new Controller2Link(this);
// NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
mResultHandler = new Handler(context.getMainLooper());
mNextSeqNumber = 0;
+ mPendingCommands = new ArrayMap<>();
+ mRequestedCommandSeqNumbers = new ArraySet<>();
if (token.getType() == TYPE_SESSION) {
connectToSession();
@@ -116,11 +131,13 @@
if (mSessionBinder != null) {
try {
mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
- mSessionBinder.disconnect(mControllerStub, mNextSeqNumber++);
+ mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
} catch (RuntimeException e) {
// No-op
}
}
+ mPendingCommands.clear();
+ mRequestedCommandSeqNumbers.clear();
mCallbackExecutor.execute(() -> {
mCallback.onDisconnected(MediaController2.this);
});
@@ -134,9 +151,8 @@
* @param command the session command
* @param args optional arguments
* @return a token which will be sent together in {@link ControllerCallback#onCommandResult}
- * when its result is received.
+ * when its result is received.
*/
- // TODO: make cancelable.
public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
if (command == null) {
throw new IllegalArgumentException("command shouldn't be null");
@@ -144,26 +160,50 @@
ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ synchronized (mLock) {
+ mPendingCommands.remove(this);
+ }
mCallbackExecutor.execute(() -> {
mCallback.onCommandResult(MediaController2.this, this,
- command, resultData);
+ command, new Session2Command.Result(resultCode, resultData));
});
}
};
synchronized (mLock) {
if (mSessionBinder != null) {
+ int seq = getNextSeqNumber();
+ mPendingCommands.put(resultReceiver, seq);
try {
- mSessionBinder.sendSessionCommand(mControllerStub, mNextSeqNumber++,
- command, args, resultReceiver);
+ mSessionBinder.sendSessionCommand(mControllerStub, seq, command, args,
+ resultReceiver);
} catch (RuntimeException e) {
- // No-op
+ mPendingCommands.remove(resultReceiver);
+ resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
}
}
}
return resultReceiver;
}
+ /**
+ * Cancels the session command previously sent.
+ *
+ * @param token the token which is returned from {@link #sendSessionCommand}.
+ */
+ public void cancelSessionCommand(@NonNull Object token) {
+ if (token == null) {
+ throw new IllegalArgumentException("token shouldn't be null");
+ }
+ synchronized (mLock) {
+ if (mSessionBinder == null) return;
+ Integer seq = mPendingCommands.remove(token);
+ if (seq != null) {
+ mSessionBinder.cancelSessionCommand(mControllerStub, seq);
+ }
+ }
+ }
+
// Called by Controller2Link.onConnected
void onConnected(int seq, Bundle connectionResult) {
final long token = Binder.clearCallingIdentity();
@@ -213,10 +253,26 @@
@Nullable ResultReceiver resultReceiver) {
final long token = Binder.clearCallingIdentity();
try {
+ synchronized (mLock) {
+ mRequestedCommandSeqNumbers.add(seq);
+ }
mCallbackExecutor.execute(() -> {
- Bundle result = mCallback.onSessionCommand(MediaController2.this, command, args);
+ boolean isCanceled;
+ synchronized (mLock) {
+ isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
+ }
+ if (isCanceled) {
+ resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ return;
+ }
+ Session2Command.Result result = mCallback.onSessionCommand(
+ MediaController2.this, command, args);
if (resultReceiver != null) {
- resultReceiver.send(0, result);
+ if (result == null) {
+ throw new RuntimeException("onSessionCommand shouldn't return null");
+ } else {
+ resultReceiver.send(result.getResultCode(), result.getResultData());
+ }
}
});
} finally {
@@ -224,6 +280,18 @@
}
}
+ // Called by Controller2Link.onSessionCommand
+ void onCancelCommand(int seq) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ mRequestedCommandSeqNumbers.remove(seq);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private int getNextSeqNumber() {
synchronized (mLock) {
return mNextSeqNumber++;
@@ -278,9 +346,11 @@
* @param controller the controller for this event
* @param command the session command
* @param args optional arguments
- * @return the result for the session command
+ * @return the result for the session command. A runtime exception will be thrown if null
+ * is returned.
*/
- public Bundle onSessionCommand(@NonNull MediaController2 controller,
+ @NonNull
+ public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller,
@NonNull Session2Command command, @Nullable Bundle args) {
return null;
}
@@ -294,7 +364,6 @@
* @param result the result of the session command
*/
public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token,
- @NonNull Session2Command command, @Nullable Bundle result) {
- }
+ @NonNull Session2Command command, @NonNull Session2Command.Result result) { }
}
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 90cfc53..4eed12f 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -902,6 +902,7 @@
map.put(MediaStore.MediaColumns.SIZE, mFileSize);
map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType);
map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm);
+ map.putNull(MediaStore.MediaColumns.HASH);
String resolution = null;
if (mWidth > 0 && mHeight > 0) {
@@ -934,7 +935,7 @@
}
} else if (MediaFile.isImageMimeType(mMimeType)) {
// FIXME - add DESCRIPTION
- } else if (mScanSuccess && MediaFile.isAudioMimeType(mMimeType)) {
+ } else if (MediaFile.isAudioMimeType(mMimeType)) {
map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0) ?
mArtist : MediaStore.UNKNOWN_STRING);
map.put(Audio.Media.ALBUM_ARTIST, (mAlbumArtist != null &&
@@ -950,10 +951,6 @@
map.put(Audio.Media.DURATION, mDuration);
map.put(Audio.Media.COMPILATION, mCompilation);
}
- if (!mScanSuccess) {
- // force mediaprovider to not determine the media type from the mime type
- map.put(Files.FileColumns.MEDIA_TYPE, 0);
- }
}
return map;
}
@@ -1056,7 +1053,7 @@
Uri tableUri = mFilesUri;
int mediaType = FileColumns.MEDIA_TYPE_NONE;
MediaInserter inserter = mMediaInserter;
- if (mScanSuccess && !mNoMedia) {
+ if (!mNoMedia) {
if (MediaFile.isVideoMimeType(mMimeType)) {
tableUri = mVideoUri;
mediaType = FileColumns.MEDIA_TYPE_VIDEO;
@@ -1131,7 +1128,7 @@
// with squashed lower case paths
values.remove(MediaStore.MediaColumns.DATA);
- if (mScanSuccess && !mNoMedia) {
+ if (!mNoMedia) {
// Changing media type must be done as separate update
if (mediaType != entry.mMediaType) {
final ContentValues mediaTypeValues = new ContentValues();
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index d67c662..b874ba46 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -20,6 +20,8 @@
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;
import static android.media.MediaConstants.KEY_SESSION2_STUB;
+import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR;
+import static android.media.Session2Command.RESULT_INFO_SKIPPED;
import static android.media.Session2Token.TYPE_SESSION;
import android.annotation.NonNull;
@@ -34,6 +36,8 @@
import android.os.Handler;
import android.os.Process;
import android.os.ResultReceiver;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import java.util.ArrayList;
@@ -112,7 +116,7 @@
}
@Override
- public void close() throws Exception {
+ public void close() {
try {
synchronized (MediaSession2.class) {
SESSION_ID_LIST.remove(mSessionId);
@@ -120,6 +124,7 @@
Collection<ControllerInfo> controllerInfos;
synchronized (mLock) {
controllerInfos = mConnectedControllers.values();
+ mConnectedControllers.clear();
mClosed = true;
}
for (ControllerInfo info : controllerInfos) {
@@ -131,6 +136,22 @@
}
/**
+ * Returns the session ID
+ */
+ @NonNull
+ public String getSessionId() {
+ return mSessionId;
+ }
+
+ /**
+ * Returns the {@link Session2Token} for creating {@link MediaController2}.
+ */
+ @NonNull
+ public Session2Token getSessionToken() {
+ return mSessionToken;
+ }
+
+ /**
* Broadcasts a session command to all the connected controllers
* <p>
* @param command the session command
@@ -158,7 +179,6 @@
* @return a token which will be sent together in {@link SessionCallback#onCommandResult}
* when its result is received.
*/
- // TODO: make cancelable.
public Object sendSessionCommand(@NonNull ControllerInfo controller,
@NonNull Session2Command command, @Nullable Bundle args) {
if (controller == null) {
@@ -169,9 +189,10 @@
}
ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ controller.receiveCommandResult(this);
mCallbackExecutor.execute(() -> {
mCallback.onCommandResult(MediaSession2.this, controller, this,
- command, resultData);
+ command, new Session2Command.Result(resultCode, resultData));
});
}
};
@@ -179,6 +200,19 @@
return resultReceiver;
}
+ /**
+ * Cancels the session command previously sent.
+ *
+ * @param controller the controller to get the session command
+ * @param token the token which is returned from {@link #sendSessionCommand}.
+ */
+ public void cancelSessionCommand(ControllerInfo controller, Object token) {
+ if (token == null) {
+ throw new IllegalArgumentException("token shouldn't be null");
+ }
+ controller.cancelSessionCommand(token);
+ }
+
boolean isClosed() {
synchronized (mLock) {
return mClosed;
@@ -296,15 +330,23 @@
// TODO: check allowed commands.
final long token = Binder.clearCallingIdentity();
try {
+ synchronized (mLock) {
+ controllerInfo.addRequestedCommandSeqNumber(seq);
+ }
+
mCallbackExecutor.execute(() -> {
- try {
- Bundle result = mCallback.onSessionCommand(
- MediaSession2.this, controllerInfo, command, args);
- if (resultReceiver != null) {
- resultReceiver.send(0, result);
+ if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
+ resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ return;
+ }
+ Session2Command.Result result = mCallback.onSessionCommand(
+ MediaSession2.this, controllerInfo, command, args);
+ if (resultReceiver != null) {
+ if (result == null) {
+ throw new RuntimeException("onSessionCommand shouldn't return null");
+ } else {
+ resultReceiver.send(result.getResultCode(), result.getResultData());
}
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
}
});
} finally {
@@ -312,6 +354,24 @@
}
}
+ // Called by Session2Link.onCancelCommand
+ void onCancelCommand(final Controller2Link controller, final int seq) {
+ final ControllerInfo controllerInfo;
+ synchronized (mLock) {
+ controllerInfo = mConnectedControllers.get(controller);
+ }
+ if (controllerInfo == null) {
+ return;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ controllerInfo.removeRequestedCommandSeqNumber(seq);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
/**
* Builder for {@link MediaSession2}.
* <p>
@@ -417,7 +477,13 @@
private final RemoteUserInfo mRemoteUserInfo;
private final boolean mIsTrusted;
private final Controller2Link mControllerBinder;
+ private final Object mLock = new Object();
+ //@GuardedBy("mLock")
private int mNextSeqNumber;
+ //@GuardedBy("mLock")
+ private ArrayMap<ResultReceiver, Integer> mPendingCommands;
+ //@GuardedBy("mLock")
+ private ArraySet<Integer> mRequestedCommandSeqNumbers;
@SuppressWarnings("WeakerAccess") /* synthetic access */
Session2CommandGroup mAllowedCommands;
@@ -425,15 +491,15 @@
/**
* @param remoteUserInfo remote user info
* @param trusted {@code true} if trusted, {@code false} otherwise
- * @param controllerBinder Controller2Link. Can be {@code null} only when a
- * MediaBrowserCompat connects to MediaSessionService and ControllerInfo is
- * needed for SessionCallback#onConnected().
+ * @param controllerBinder Controller2Link for the connected controller.
*/
ControllerInfo(@NonNull RemoteUserInfo remoteUserInfo, boolean trusted,
@Nullable Controller2Link controllerBinder) {
mRemoteUserInfo = remoteUserInfo;
mIsTrusted = trusted;
mControllerBinder = controllerBinder;
+ mPendingCommands = new ArrayMap<>();
+ mRequestedCommandSeqNumbers = new ArraySet<>();
}
/**
@@ -517,16 +583,53 @@
void sendSessionCommand(Session2Command command, Bundle args,
ResultReceiver resultReceiver) {
if (mControllerBinder == null) return;
+
try {
int seq = getNextSeqNumber();
+ synchronized (mLock) {
+ mPendingCommands.put(resultReceiver, seq);
+ }
mControllerBinder.sendSessionCommand(seq, command, args, resultReceiver);
} catch (RuntimeException e) {
// Controller may be died prematurely.
+ synchronized (mLock) {
+ mPendingCommands.remove(resultReceiver);
+ }
+ resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
+ }
+ }
+
+ void cancelSessionCommand(@NonNull Object token) {
+ if (mControllerBinder == null) return;
+ Integer seq;
+ synchronized (mLock) {
+ seq = mPendingCommands.remove(token);
+ }
+ if (seq != null) {
+ mControllerBinder.cancelSessionCommand(seq);
+ }
+ }
+
+ void receiveCommandResult(ResultReceiver resultReceiver) {
+ synchronized (mLock) {
+ mPendingCommands.remove(resultReceiver);
+ }
+ }
+
+ void addRequestedCommandSeqNumber(int seq) {
+ synchronized (mLock) {
+ mRequestedCommandSeqNumbers.add(seq);
+ }
+ }
+
+ boolean removeRequestedCommandSeqNumber(int seq) {
+ synchronized (mLock) {
+ return mRequestedCommandSeqNumbers.remove(seq);
}
}
private int getNextSeqNumber() {
- synchronized (this) {
+ synchronized (mLock) {
return mNextSeqNumber++;
}
}
@@ -575,9 +678,11 @@
* @param controller controller information
* @param command the session command
* @param args optional arguments
- * @return The result for the session command
+ * @return the result for the session command. A runtime exception will be thrown if null
+ * is returned.
*/
- public Bundle onSessionCommand(@NonNull MediaSession2 session,
+ @NonNull
+ public Session2Command.Result onSessionCommand(@NonNull MediaSession2 session,
@NonNull ControllerInfo controller, @NonNull Session2Command command,
@Nullable Bundle args) {
return null;
@@ -594,8 +699,6 @@
*/
public void onCommandResult(@NonNull MediaSession2 session,
@NonNull ControllerInfo controller, @NonNull Object token,
- @NonNull Session2Command command, @Nullable Bundle result) {
- }
+ @NonNull Session2Command command, @NonNull Session2Command.Result result) { }
}
}
-
diff --git a/media/java/android/media/Session2Command.java b/media/java/android/media/Session2Command.java
index a5e2ae4..e46e64e 100644
--- a/media/java/android/media/Session2Command.java
+++ b/media/java/android/media/Session2Command.java
@@ -409,6 +409,112 @@
*/
public static final int COMMAND_CODE_SESSION_SET_RATING = 40010;
+ /**
+ * @hide
+ */
+ @IntDef(flag = false, /*prefix = "RESULT_CODE",*/ value = {
+ RESULT_SUCCESS,
+ RESULT_ERROR_UNKNOWN_ERROR,
+ RESULT_ERROR_INVALID_STATE,
+ RESULT_ERROR_BAD_VALUE,
+ RESULT_ERROR_PERMISSION_DENIED,
+ RESULT_ERROR_IO_ERROR,
+ RESULT_INFO_SKIPPED,
+ RESULT_ERROR_SESSION_DISCONNECTED,
+ RESULT_ERROR_NOT_SUPPORTED,
+ RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED,
+ RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED,
+ RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT,
+ RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED,
+ RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION,
+ RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED,
+ RESULT_ERROR_SESSION_SETUP_REQUIRED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResultCode {}
+
+ /**
+ * Result code representing that the command is skipped or canceled. For an example, a seek
+ * command can be skipped if it is followed by another seek command.
+ */
+ public static final int RESULT_INFO_SKIPPED = 1;
+
+ /**
+ * Result code representing that the command is successfully completed.
+ */
+ public static final int RESULT_SUCCESS = 0;
+
+ /**
+ * Result code represents that call is ended with an unknown error.
+ */
+ public static final int RESULT_ERROR_UNKNOWN_ERROR = -1;
+
+ /**
+ * Result code representing that the command cannot be completed because the current state is
+ * not valid for the command.
+ */
+ public static final int RESULT_ERROR_INVALID_STATE = -2;
+
+ /**
+ * Result code representing that an argument is illegal.
+ */
+ public static final int RESULT_ERROR_BAD_VALUE = -3;
+
+ /**
+ * Result code representing that the command is not allowed.
+ */
+ public static final int RESULT_ERROR_PERMISSION_DENIED = -4;
+
+ /**
+ * Result code representing a file or network related command error.
+ */
+ public static final int RESULT_ERROR_IO_ERROR = -5;
+
+ /**
+ * Result code representing that the command is not supported nor implemented.
+ */
+ public static final int RESULT_ERROR_NOT_SUPPORTED = -6;
+
+ /**
+ * Result code representing that the session and controller were disconnected.
+ */
+ public static final int RESULT_ERROR_SESSION_DISCONNECTED = -100;
+
+ /**
+ * Result code representing that the authentication has expired.
+ */
+ public static final int RESULT_ERROR_SESSION_AUTHENTICATION_EXPIRED = -102;
+
+ /**
+ * Result code representing that a premium account is required.
+ */
+ public static final int RESULT_ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED = -103;
+
+ /**
+ * Result code representing that too many concurrent streams are detected.
+ */
+ public static final int RESULT_ERROR_SESSION_CONCURRENT_STREAM_LIMIT = -104;
+
+ /**
+ * Result code representing that the content is blocked due to parental controls.
+ */
+ public static final int RESULT_ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED = -105;
+
+ /**
+ * Result code representing that the content is blocked due to being regionally unavailable.
+ */
+ public static final int RESULT_ERROR_SESSION_NOT_AVAILABLE_IN_REGION = -106;
+
+ /**
+ * Result code representing that the application cannot skip any more because the skip limit is
+ * reached.
+ */
+ public static final int RESULT_ERROR_SESSION_SKIP_LIMIT_REACHED = -107;
+
+ /**
+ * Result code representing that the session needs user's manual intervention.
+ */
+ public static final int RESULT_ERROR_SESSION_SETUP_REQUIRED = -108;
+
public static final Parcelable.Creator<Session2Command> CREATOR =
new Parcelable.Creator<Session2Command>() {
@Override
@@ -582,6 +688,39 @@
return Objects.hash(mCustomCommand, mCommandCode);
}
+ /**
+ * Contains the result of {@link Session2Command}.
+ */
+ public static final class Result {
+ private final int mResultCode;
+ private final Bundle mResultData;
+
+ /**
+ * Constructor of {@link Result}.
+ *
+ * @param resultCode result code
+ * @param resultData result data
+ */
+ public Result(int resultCode, Bundle resultData) {
+ mResultCode = resultCode;
+ mResultData = resultData;
+ }
+
+ /**
+ * Returns the result code.
+ */
+ public int getResultCode() {
+ return mResultCode;
+ }
+
+ /**
+ * Returns the result data.
+ */
+ public Bundle getResultData() {
+ return mResultData;
+ }
+ }
+
@SuppressWarnings("WeakerAccess") /* synthetic access */
static final class Range {
public final int lower;
diff --git a/media/java/android/media/Session2Link.java b/media/java/android/media/Session2Link.java
index 57c58dc..5fe558d 100644
--- a/media/java/android/media/Session2Link.java
+++ b/media/java/android/media/Session2Link.java
@@ -28,8 +28,7 @@
import java.util.Objects;
/**
- * Handles incoming commands from {@link MediaController2} and {@link MediaBrowser2}
- * to both {@link MediaSession2} and {@link MediaLibrarySession}.
+ * Handles incoming commands from {@link MediaController2} to {@link MediaSession2}.
* @hide
*/
// @SystemApi
@@ -113,7 +112,7 @@
try {
mISession.connect(caller, seq, connectionRequest);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
}
}
@@ -122,7 +121,7 @@
try {
mISession.disconnect(caller, seq);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
}
}
@@ -132,7 +131,16 @@
try {
mISession.sendSessionCommand(caller, seq, command, args, resultReceiver);
} catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Interface method for IMediaSession2.sendSessionCommand */
+ public void cancelSessionCommand(final Controller2Link caller, final int seq) {
+ try {
+ mISession.cancelSessionCommand(caller, seq);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
}
}
@@ -152,6 +160,11 @@
mSession.onSessionCommand(caller, seq, command, args, resultReceiver);
}
+ /** Stub implementation for IMediaSession2.cancelSessionCommand */
+ public void onCancelCommand(final Controller2Link caller, final int seq) {
+ mSession.onCancelCommand(caller, seq);
+ }
+
private class Session2Stub extends IMediaSession2.Stub {
@Override
public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
@@ -168,5 +181,10 @@
final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver);
}
+
+ @Override
+ public void cancelSessionCommand(final Controller2Link caller, final int seq) {
+ Session2Link.this.onCancelCommand(caller, seq);
+ }
}
}
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 7fb3aa6..1c6210e 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -165,6 +165,20 @@
}
/** @hide */
+ public boolean isRoutedToDevice(int deviceType, @NonNull String deviceAddress) {
+ if ((mRouteFlags & ROUTE_FLAG_RENDER) != ROUTE_FLAG_RENDER) {
+ return false;
+ }
+ if (deviceType != mDeviceSystemType) {
+ return false;
+ }
+ if (!deviceAddress.equals(mDeviceAddress)) {
+ return false;
+ }
+ return true;
+ }
+
+ /** @hide */
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 6103f557..65f3294 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
+import android.media.AudioDeviceInfo;
import android.media.AudioFocusInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
@@ -323,6 +324,80 @@
}
}
+ /**
+ * @hide
+ * Configures the audio framework so that all audio stream originating from the given UID
+ * can only come from a set of audio devices.
+ * For this routing to be operational, a number of {@link AudioMix} instances must have been
+ * previously registered on this policy, and routed to a super-set of the given audio devices
+ * with {@link AudioMix.Builder#setDevice(android.media.AudioDeviceInfo)}. Note that having
+ * multiple devices in the list doesn't imply the signals will be duplicated on the different
+ * audio devices, final routing will depend on the {@link AudioAttributes} of the sounds being
+ * played.
+ * @param uid UID of the application to affect.
+ * @param devices list of devices to which the audio stream of the application may be routed.
+ * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR}
+ * otherwise.
+ */
+ @SystemApi
+ public int setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
+ if (devices == null) {
+ throw new IllegalArgumentException("Illegal null list of audio devices");
+ }
+ synchronized (mLock) {
+ if (mStatus != POLICY_STATUS_REGISTERED) {
+ throw new IllegalStateException("Cannot use unregistered AudioPolicy");
+ }
+ final int[] deviceTypes = new int[devices.size()];
+ final String[] deviceAdresses = new String[devices.size()];
+ int i = 0;
+ for (AudioDeviceInfo device : devices) {
+ if (device == null) {
+ throw new IllegalArgumentException(
+ "Illegal null AudioDeviceInfo in setUidDeviceAffinity");
+ }
+ deviceTypes[i] =
+ AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
+ deviceAdresses[i] = device.getAddress();
+ i++;
+ }
+ final IAudioService service = getService();
+ try {
+ final int status = service.setUidDeviceAffinity(this.cb(),
+ uid, deviceTypes, deviceAdresses);
+ return status;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setUidDeviceAffinity", e);
+ return AudioManager.ERROR;
+ }
+ }
+ }
+
+ /**
+ * @hide
+ * Removes audio device affinity previously set by
+ * {@link #setUidDeviceAffinity(int, java.util.List)}.
+ * @param uid UID of the application affected.
+ * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR}
+ * otherwise.
+ */
+ @SystemApi
+ public int removeUidDeviceAffinity(int uid) {
+ synchronized (mLock) {
+ if (mStatus != POLICY_STATUS_REGISTERED) {
+ throw new IllegalStateException("Cannot use unregistered AudioPolicy");
+ }
+ final IAudioService service = getService();
+ try {
+ final int status = service.removeUidDeviceAffinity(this.cb(), uid);
+ return status;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in removeUidDeviceAffinity", e);
+ return AudioManager.ERROR;
+ }
+ }
+ }
+
public void setRegistration(String regId) {
synchronized (mLock) {
mRegistrationId = regId;
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 5c1915b..f0db1b4 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -47,9 +47,9 @@
PendingIntent getLaunchPendingIntent();
long getFlags();
ParcelableVolumeInfo getVolumeAttributes();
- void adjustVolume(String packageName, in ControllerCallbackLink caller,
+ void adjustVolume(String packageName, String opPackageName, in ControllerCallbackLink caller,
boolean asSystemService, int direction, int flags);
- void setVolumeTo(String packageName, in ControllerCallbackLink caller,
+ void setVolumeTo(String packageName, String opPackageName, in ControllerCallbackLink caller,
int value, int flags);
// These commands are for the TransportControls
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 5801967..f2c0e32 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -35,9 +35,10 @@
List<IBinder> getSessions(in ComponentName compName, int userId);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
- void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
- int stream, boolean musicOnly);
- void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags);
+ void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService,
+ in KeyEvent keyEvent, int stream, boolean musicOnly);
+ void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream,
+ int delta, int flags);
void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
int userId);
void removeSessionsListener(in IActiveSessionsListener listener);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 5eb77f9..7b061fe 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -154,7 +154,7 @@
return false;
}
try {
- return mSessionBinder.sendMediaButton(mContext.getOpPackageName(), mCbStub,
+ return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
asSystemService, keyEvent);
} catch (RemoteException e) {
// System is dead. =(
@@ -187,8 +187,12 @@
break;
}
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true,
- direction, AudioManager.FLAG_SHOW_UI);
+ // Note: Need both package name and OP package name. Package name is used for
+ // RemoteUserInfo, and OP package name is used for AudioService's internal
+ // AppOpsManager usages.
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, direction,
+ AudioManager.FLAG_SHOW_UI);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -198,8 +202,11 @@
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY;
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true, 0,
- flags);
+ // Note: Need both package name and OP package name. Package name is used for
+ // RemoteUserInfo, and OP package name is used for AudioService's internal
+ // AppOpsManager usages.
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, 0, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -365,7 +372,11 @@
*/
public void setVolumeTo(int value, int flags) {
try {
- mSessionBinder.setVolumeTo(mContext.getOpPackageName(), mCbStub, value, flags);
+ // Note: Need both package name and OP package name. Package name is used for
+ // RemoteUserInfo, and OP package name is used for AudioService's internal
+ // AppOpsManager usages.
+ mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, value, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e);
}
@@ -386,8 +397,11 @@
*/
public void adjustVolume(int direction, int flags) {
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, false, direction,
- flags);
+ // Note: Need both package name and OP package name. Package name is used for
+ // RemoteUserInfo, and OP package name is used for AudioService's internal
+ // AppOpsManager usages.
+ mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, false, direction, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
@@ -453,7 +467,7 @@
throw new IllegalArgumentException("command cannot be null or empty");
}
try {
- mSessionBinder.sendCommand(mContext.getOpPackageName(), mCbStub, command, args, cb);
+ mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCommand.", e);
}
@@ -519,7 +533,7 @@
if (!mCbRegistered) {
try {
- mSessionBinder.registerCallbackListener(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
mCbRegistered = true;
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerCallback", e);
@@ -666,7 +680,7 @@
*/
public void prepare() {
try {
- mSessionBinder.prepare(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare.", e);
}
@@ -690,7 +704,7 @@
"You must specify a non-empty String for prepareFromMediaId.");
}
try {
- mSessionBinder.prepareFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
+ mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
@@ -717,7 +731,7 @@
query = "";
}
try {
- mSessionBinder.prepareFromSearch(mContext.getOpPackageName(), mCbStub, query,
+ mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
@@ -742,7 +756,7 @@
"You must specify a non-empty Uri for prepareFromUri.");
}
try {
- mSessionBinder.prepareFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
+ mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
}
@@ -753,7 +767,7 @@
*/
public void play() {
try {
- mSessionBinder.play(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.play(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play.", e);
}
@@ -772,7 +786,7 @@
"You must specify a non-empty String for playFromMediaId.");
}
try {
- mSessionBinder.playFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
+ mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
@@ -795,7 +809,7 @@
query = "";
}
try {
- mSessionBinder.playFromSearch(mContext.getOpPackageName(), mCbStub, query, extras);
+ mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e);
}
@@ -814,7 +828,7 @@
"You must specify a non-empty Uri for playFromUri.");
}
try {
- mSessionBinder.playFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
+ mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e);
}
@@ -826,7 +840,7 @@
*/
public void skipToQueueItem(long id) {
try {
- mSessionBinder.skipToQueueItem(mContext.getOpPackageName(), mCbStub, id);
+ mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
@@ -838,7 +852,7 @@
*/
public void pause() {
try {
- mSessionBinder.pause(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.pause(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling pause.", e);
}
@@ -850,7 +864,7 @@
*/
public void stop() {
try {
- mSessionBinder.stop(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.stop(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling stop.", e);
}
@@ -863,7 +877,7 @@
*/
public void seekTo(long pos) {
try {
- mSessionBinder.seekTo(mContext.getOpPackageName(), mCbStub, pos);
+ mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling seekTo.", e);
}
@@ -875,7 +889,7 @@
*/
public void fastForward() {
try {
- mSessionBinder.fastForward(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling fastForward.", e);
}
@@ -886,7 +900,7 @@
*/
public void skipToNext() {
try {
- mSessionBinder.next(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.next(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling next.", e);
}
@@ -898,7 +912,7 @@
*/
public void rewind() {
try {
- mSessionBinder.rewind(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rewind.", e);
}
@@ -909,7 +923,7 @@
*/
public void skipToPrevious() {
try {
- mSessionBinder.previous(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.previous(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling previous.", e);
}
@@ -924,7 +938,7 @@
*/
public void setRating(Rating rating) {
try {
- mSessionBinder.rate(mContext.getOpPackageName(), mCbStub, rating);
+ mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rate.", e);
}
@@ -959,7 +973,7 @@
throw new IllegalArgumentException("CustomAction cannot be null.");
}
try {
- mSessionBinder.sendCustomAction(mContext.getOpPackageName(), mCbStub, action, args);
+ mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e);
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 73dd55c..7a4116f 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -312,7 +312,7 @@
private void dispatchMediaKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
boolean needWakeLock) {
try {
- mService.dispatchMediaKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent,
+ mService.dispatchMediaKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
needWakeLock);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send key event.", e);
@@ -348,8 +348,8 @@
private void dispatchVolumeKeyEventInternal(boolean asSystemService, @NonNull KeyEvent keyEvent,
int stream, boolean musicOnly) {
try {
- mService.dispatchVolumeKeyEvent(mContext.getOpPackageName(), asSystemService, keyEvent,
- stream, musicOnly);
+ mService.dispatchVolumeKeyEvent(mContext.getPackageName(), mContext.getOpPackageName(),
+ asSystemService, keyEvent, stream, musicOnly);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send volume key event.", e);
}
@@ -369,8 +369,8 @@
*/
public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
try {
- mService.dispatchAdjustVolume(mContext.getOpPackageName(), suggestedStream, direction,
- flags);
+ mService.dispatchAdjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
+ suggestedStream, direction, flags);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send adjust volume.", e);
}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 7481fff..f75f69b 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -95,14 +95,16 @@
],
shared_libs: [
- "android.hardware.cas@1.0", // for CasManager. VNDK???
- "android.hardware.cas.native@1.0", // CasManager. VNDK???
+ // MediaCas
+ "android.hardware.cas@1.0",
+ "android.hardware.cas.native@1.0",
"android.hidl.allocator@1.0",
+ "libhidlbase",
"libhidlmemory",
- "libbinder",
- "libgui", // for VideoFrameScheduler
- "libhidlbase", // VNDK???
- "libpowermanager", // for JWakeLock. to be removed
+
+ "libpowermanager", // Used by JWakeLock. Will be replace with public SDJ API.
+ "libmediametrics", // Used by MediaMetrics. Will be replaced with stable C API.
+ "libbinder", // Used by JWakeLock and MediaMetrics.
"libutils", // Have to use shared lib to make libandroid_runtime behave correctly.
// Otherwise, AndroidRuntime::getJNIEnv() will return NULL.
@@ -124,7 +126,6 @@
"libmedia_helper",
"libmedia_player2_util",
"libmediaextractor",
- "libmediametrics",
"libmediaplayer2",
"libmediaplayer2-protos",
"libmediandk_utils",
diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp
index 96c9c1c..0936256 100644
--- a/native/webview/plat_support/Android.bp
+++ b/native/webview/plat_support/Android.bp
@@ -22,6 +22,7 @@
name: "libwebviewchromium_plat_support",
srcs: [
+ "draw_functor.cpp",
"draw_gl_functor.cpp",
"draw_vk_functor.cpp",
"functor_utils.cpp",
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index 8d48a58..6afd883 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -129,31 +129,31 @@
// Called on render thread while UI thread is blocked. Called for both GL and
// VK.
-typedef void AwDrawFn_OnSync(int functor, AwDrawFn_OnSyncParams* params);
+typedef void AwDrawFn_OnSync(int functor, void* data, AwDrawFn_OnSyncParams* params);
// Called on render thread when either the context is destroyed _or_ when the
// functor's last reference goes away. Will always be called with an active
// context. Called for both GL and VK.
-typedef void AwDrawFn_OnContextDestroyed(int functor);
+typedef void AwDrawFn_OnContextDestroyed(int functor, void* data);
// Called on render thread when the last reference to the handle goes away and
-// the handle is considered irrevocably destroyed. Will always be proceeded by
+// the handle is considered irrevocably destroyed. Will always be preceded by
// a call to OnContextDestroyed if this functor had ever been drawn. Called for
// both GL and VK.
-typedef void AwDrawFn_OnDestroyed(int functor);
+typedef void AwDrawFn_OnDestroyed(int functor, void* data);
// Only called for GL.
-typedef void AwDrawFn_DrawGL(int functor, AwDrawFn_DrawGLParams* params);
+typedef void AwDrawFn_DrawGL(int functor, void* data, AwDrawFn_DrawGLParams* params);
// Initialize vulkan state. Needs to be called again after any
// OnContextDestroyed. Only called for Vulkan.
-typedef void AwDrawFn_InitVk(int functor, AwDrawFn_InitVkParams* params);
+typedef void AwDrawFn_InitVk(int functor, void* data, AwDrawFn_InitVkParams* params);
// Only called for Vulkan.
-typedef void AwDrawFn_DrawVk(int functor, AwDrawFn_DrawVkParams* params);
+typedef void AwDrawFn_DrawVk(int functor, void* data, AwDrawFn_DrawVkParams* params);
// Only called for Vulkan.
-typedef void AwDrawFn_PostDrawVk(int functor,
+typedef void AwDrawFn_PostDrawVk(int functor, void* data,
AwDrawFn_PostDrawVkParams* params);
struct AwDrawFnFunctorCallbacks {
@@ -176,7 +176,7 @@
typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void);
// Create a functor. |functor_callbacks| should be valid until OnDestroyed.
-typedef int AwDrawFn_CreateFunctor(AwDrawFnFunctorCallbacks* functor_callbacks);
+typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks);
// May be called on any thread to signal that the functor should be destroyed.
// The functor will receive an onDestroyed when the last usage of it is
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
new file mode 100644
index 0000000..820bac5
--- /dev/null
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include "draw_fn.h"
+
+#include <jni.h>
+#include <private/hwui/WebViewFunctor.h>
+#include <utils/Log.h>
+
+#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#define COMPILE_ASSERT(expr, err) \
+__unused static const char (err)[(expr) ? 1 : -1] = "";
+
+namespace android {
+namespace {
+
+struct SupportData {
+ void* const data;
+ AwDrawFnFunctorCallbacks callbacks;
+};
+
+void onSync(int functor, void* data,
+ const uirenderer::WebViewSyncData& syncData) {
+ AwDrawFn_OnSyncParams params = {
+ .version = kAwDrawFnVersion,
+ .apply_force_dark = syncData.applyForceDark,
+ };
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_sync(functor, support->data, ¶ms);
+}
+
+void onContextDestroyed(int functor, void* data) {
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_context_destroyed(functor, support->data);
+}
+
+void onDestroyed(int functor, void* data) {
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.on_destroyed(functor, support->data);
+ delete support;
+}
+
+void draw_gl(int functor, void* data,
+ const uirenderer::DrawGlInfo& draw_gl_params) {
+ AwDrawFn_DrawGLParams params = {
+ .version = kAwDrawFnVersion,
+ .clip_left = draw_gl_params.clipLeft,
+ .clip_top = draw_gl_params.clipTop,
+ .clip_right = draw_gl_params.clipRight,
+ .clip_bottom = draw_gl_params.clipBottom,
+ .width = draw_gl_params.width,
+ .height = draw_gl_params.height,
+ .is_layer = draw_gl_params.isLayer,
+ };
+ COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform),
+ mismatched_transform_matrix_sizes);
+ for (int i = 0; i < NELEM(params.transform); ++i) {
+ params.transform[i] = draw_gl_params.transform[i];
+ }
+ SupportData* support = static_cast<SupportData*>(data);
+ support->callbacks.draw_gl(functor, support->data, ¶ms);
+}
+
+int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
+ static bool callbacks_initialized = false;
+ static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
+ .onSync = &onSync,
+ .onContextDestroyed = &onContextDestroyed,
+ .onDestroyed = &onDestroyed,
+ };
+ if (!callbacks_initialized) {
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ webview_functor_callbacks.gles.draw = &draw_gl;
+ break;
+ case uirenderer::RenderMode::Vulkan:
+ break;
+ }
+ callbacks_initialized = true;
+ }
+ SupportData* support = new SupportData{
+ .data = data,
+ .callbacks = *functor_callbacks,
+ };
+ int functor = uirenderer::WebViewFunctor_create(
+ support, webview_functor_callbacks,
+ uirenderer::WebViewFunctor_queryPlatformRenderMode());
+ if (functor <= 0) delete support;
+ return functor;
+}
+
+void ReleaseFunctor(int functor) {
+ uirenderer::WebViewFunctor_release(functor);
+}
+
+AwDrawFnRenderMode QueryRenderMode(void) {
+ switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+ case uirenderer::RenderMode::OpenGL_ES:
+ return AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
+ case uirenderer::RenderMode::Vulkan:
+ return AW_DRAW_FN_RENDER_MODE_VULKAN;
+ }
+}
+
+jlong GetDrawFnFunctionTable() {
+ static AwDrawFnFunctionTable function_table = {
+ .version = kAwDrawFnVersion,
+ .query_render_mode = &QueryRenderMode,
+ .create_functor = &CreateFunctor,
+ .release_functor = &ReleaseFunctor,
+ };
+ return reinterpret_cast<intptr_t>(&function_table);
+}
+
+const char kClassName[] = "com/android/webview/chromium/DrawFunctor";
+const JNINativeMethod kJniMethods[] = {
+ {"nativeGetFunctionTable", "()J",
+ reinterpret_cast<void*>(GetDrawFnFunctionTable)},
+};
+
+} // namespace
+
+void RegisterDrawFunctor(JNIEnv* env) {
+ jclass clazz = env->FindClass(kClassName);
+ LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName);
+
+ int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res);
+}
+
+} // namespace android
diff --git a/native/webview/plat_support/jni_entry_point.cpp b/native/webview/plat_support/jni_entry_point.cpp
index 4771be1..9599fa6 100644
--- a/native/webview/plat_support/jni_entry_point.cpp
+++ b/native/webview/plat_support/jni_entry_point.cpp
@@ -21,6 +21,7 @@
namespace android {
+void RegisterDrawFunctor(JNIEnv* env);
void RegisterDrawGLFunctor(JNIEnv* env);
void RegisterGraphicsUtils(JNIEnv* env);
@@ -30,6 +31,7 @@
JNIEnv* env = NULL;
jint ret = vm->AttachCurrentThread(&env, NULL);
LOG_ALWAYS_FATAL_IF(ret != JNI_OK, "AttachCurrentThread failed");
+ android::RegisterDrawFunctor(env);
android::RegisterDrawGLFunctor(env);
android::RegisterGraphicsUtils(env);
diff --git a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index d5dd3c3..4ef926f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/CarSystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -28,7 +28,7 @@
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher;
/**
* A view that forms the header of the notification panel. This view will ensure that any
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
index 5bf30ca..b36a7da 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
@@ -45,9 +45,7 @@
Log.d(TAG, "IVoiceInteractionSessionShowCallback onShown()");
}
};
-
- private static final String EXTRA_CAR_PUSH_TO_TALK =
- "com.android.car.input.EXTRA_CAR_PUSH_TO_TALK";
+
private final AssistUtils mAssistUtils;
public AssitantButton(Context context, AttributeSet attrs) {
@@ -60,7 +58,6 @@
private void showAssistant() {
final Bundle args = new Bundle();
- args.putBoolean(EXTRA_CAR_PUSH_TO_TALK, true);
mAssistUtils.showSessionForActiveService(args,
SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, /*activityToken=*/ null);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 7028999c..dbddf71 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -280,7 +280,9 @@
buildNavBarContent();
attachNavBarWindows();
- mNavigationBarController.createNavigationBars();
+ // There has been a car customized nav bar on the default display, so just create nav bars
+ // on external displays.
+ mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */);
}
private void buildNavBarContent() {
@@ -447,12 +449,6 @@
}
}
-
- @Override
- public View getNavigationBarWindow() {
- return mNavigationBarWindow;
- }
-
@Override
protected View.OnTouchListener getStatusBarWindowTouchListener() {
// Usually, a touch on the background window will dismiss the notification shade. However,
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
index 305862a..0a4b24c 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
@@ -168,6 +168,7 @@
if (mDetailsId == 0) {
detailsView.setVisibility(View.GONE);
} else {
+ detailsView.setVisibility(View.VISIBLE);
detailsView.setText(mDetailsId);
detailsView.setOnClickListener(mDetailsOnClickListener);
}
diff --git a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml
index cbebbb3..d6dc211 100644
--- a/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml
+++ b/packages/SettingsLib/SettingsSpinner/res/drawable/settings_spinner_background.xml
@@ -18,12 +18,11 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack">
<item>
- <shape
- android:tint="?android:attr/colorForeground">
+ <shape>
<corners
android:radius="20dp"/>
<solid
- android:color="@android:color/transparent"/>
+ android:color="?android:attr/colorPrimary"/>
<stroke
android:color="#1f000000"
android:width="1dp"/>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 842779d..7dcc3ac 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1138,7 +1138,7 @@
<string name="notice_header" translatable="false"></string>
<!-- UI debug setting: opt in to use updated graphics driver? [CHAR LIMIT=100] -->
- <string name="updated_gfx_driver_dev_opt_in_app_summary">Opt in app to use updated graphcis driver in developement</string>
+ <string name="gup_dev_opt_in_app_summary">Opt in app to use Game Update Package in developement</string>
<!-- Name of the phone device [CHAR LIMIT=NONE] -->
<string name="media_transfer_phone_device_name">Phone speaker</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
index 9af0670..4ac3ce4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationAccesses.java
@@ -31,6 +31,7 @@
import androidx.annotation.VisibleForTesting;
+import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -56,11 +57,18 @@
private final PackageManager mPackageManager;
private final Context mContext;
private final IconDrawableFactory mDrawableFactory;
+ private final Clock mClock;
public RecentLocationAccesses(Context context) {
+ this(context, Clock.systemDefaultZone());
+ }
+
+ @VisibleForTesting
+ RecentLocationAccesses(Context context, Clock clock) {
mContext = context;
mPackageManager = context.getPackageManager();
mDrawableFactory = IconDrawableFactory.newInstance(context);
+ mClock = clock;
}
/**
@@ -77,7 +85,7 @@
// Process the AppOps list and generate a preference list.
ArrayList<Access> accesses = new ArrayList<>(appOpsCount);
- final long now = System.currentTimeMillis();
+ final long now = mClock.millis();
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
final List<UserHandle> profiles = um.getUserProfiles();
@@ -175,7 +183,7 @@
public final CharSequence contentDescription;
public final long accessFinishTime;
- private Access(String packageName, UserHandle userHandle, Drawable icon,
+ public Access(String packageName, UserHandle userHandle, Drawable icon,
CharSequence label, CharSequence contentDescription,
long accessFinishTime) {
this.packageName = packageName;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
new file mode 100644
index 0000000..d5b89ca
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -0,0 +1,162 @@
+package com.android.settingslib.location;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.PackageOps;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.time.Clock;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(RobolectricTestRunner.class)
+public class RecentLocationAccessesTest {
+
+ private static final int TEST_UID = 1234;
+ private static final long NOW = 1_000_000_000; // Approximately 9/8/2001
+ private static final long ONE_MIN_AGO = NOW - TimeUnit.MINUTES.toMillis(1);
+ private static final long TWENTY_THREE_HOURS_AGO = NOW - TimeUnit.HOURS.toMillis(23);
+ private static final long TWO_DAYS_AGO = NOW - TimeUnit.DAYS.toMillis(2);
+ private static final String[] TEST_PACKAGE_NAMES =
+ {"package_1MinAgo", "package_14MinAgo", "package_20MinAgo"};
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private AppOpsManager mAppOpsManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Clock mClock;
+ private Context mContext;
+ private int mTestUserId;
+ private RecentLocationAccesses mRecentLocationAccesses;
+
+ @Before
+ public void setUp() throws NameNotFoundException {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mPackageManager.getApplicationLabel(isA(ApplicationInfo.class)))
+ .thenReturn("testApplicationLabel");
+ when(mPackageManager.getUserBadgedLabel(isA(CharSequence.class), isA(UserHandle.class)))
+ .thenReturn("testUserBadgedLabel");
+ mTestUserId = UserHandle.getUserId(TEST_UID);
+ when(mUserManager.getUserProfiles())
+ .thenReturn(Collections.singletonList(new UserHandle(mTestUserId)));
+
+ long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO};
+ List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
+ when(mAppOpsManager.getPackagesForOps(RecentLocationAccesses.LOCATION_OPS)).thenReturn(
+ appOps);
+ mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES);
+
+ when(mClock.millis()).thenReturn(NOW);
+ mRecentLocationAccesses = new RecentLocationAccesses(mContext, mClock);
+ }
+
+ @Test
+ public void testGetAppList_shouldFilterRecentAccesses() {
+ List<RecentLocationAccesses.Access> requests = mRecentLocationAccesses.getAppList();
+ // Only two of the apps have requested location within 15 min.
+ assertThat(requests).hasSize(2);
+ // Make sure apps are ordered by recency
+ assertThat(requests.get(0).packageName).isEqualTo(TEST_PACKAGE_NAMES[0]);
+ assertThat(requests.get(0).accessFinishTime).isEqualTo(ONE_MIN_AGO);
+ assertThat(requests.get(1).packageName).isEqualTo(TEST_PACKAGE_NAMES[1]);
+ assertThat(requests.get(1).accessFinishTime).isEqualTo(TWENTY_THREE_HOURS_AGO);
+ }
+
+ @Test
+ public void testGetAppList_shouldNotShowAndroidOS() throws NameNotFoundException {
+ // Add android OS to the list of apps.
+ PackageOps androidSystemPackageOps =
+ createPackageOps(
+ RecentLocationAccesses.ANDROID_SYSTEM_PACKAGE_NAME,
+ Process.SYSTEM_UID,
+ AppOpsManager.OP_FINE_LOCATION,
+ ONE_MIN_AGO);
+ long[] testRequestTime =
+ {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO};
+ List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
+ appOps.add(androidSystemPackageOps);
+ when(mAppOpsManager.getPackagesForOps(RecentLocationAccesses.LOCATION_OPS)).thenReturn(
+ appOps);
+ mockTestApplicationInfos(
+ Process.SYSTEM_UID, RecentLocationAccesses.ANDROID_SYSTEM_PACKAGE_NAME);
+
+ List<RecentLocationAccesses.Access> requests = mRecentLocationAccesses.getAppList();
+ // Android OS shouldn't show up in the list of apps.
+ assertThat(requests).hasSize(2);
+ // Make sure apps are ordered by recency
+ assertThat(requests.get(0).packageName).isEqualTo(TEST_PACKAGE_NAMES[0]);
+ assertThat(requests.get(0).accessFinishTime).isEqualTo(ONE_MIN_AGO);
+ assertThat(requests.get(1).packageName).isEqualTo(TEST_PACKAGE_NAMES[1]);
+ assertThat(requests.get(1).accessFinishTime).isEqualTo(TWENTY_THREE_HOURS_AGO);
+ }
+
+ private void mockTestApplicationInfos(int userId, String... packageNameList)
+ throws NameNotFoundException {
+ for (String packageName : packageNameList) {
+ ApplicationInfo appInfo = new ApplicationInfo();
+ appInfo.packageName = packageName;
+ when(mPackageManager.getApplicationInfoAsUser(
+ packageName, PackageManager.GET_META_DATA, userId)).thenReturn(appInfo);
+ }
+ }
+
+ private List<PackageOps> createTestPackageOpsList(String[] packageNameList, long[] time) {
+ List<PackageOps> packageOpsList = new ArrayList<>();
+ for (int i = 0; i < packageNameList.length; i++) {
+ PackageOps packageOps = createPackageOps(
+ packageNameList[i],
+ TEST_UID,
+ AppOpsManager.OP_FINE_LOCATION,
+ time[i]);
+ packageOpsList.add(packageOps);
+ }
+ return packageOpsList;
+ }
+
+ private PackageOps createPackageOps(String packageName, int uid, int op, long time) {
+ return new PackageOps(
+ packageName,
+ uid,
+ Collections.singletonList(createOpEntryWithTime(op, time)));
+ }
+
+ private OpEntry createOpEntryWithTime(int op, long time) {
+ final long[] times = new long[AppOpsManager._NUM_UID_STATE];
+ // Slot for background access timestamp.
+ times[AppOpsManager.UID_STATE_LAST_NON_RESTRICTED + 1] = time;
+ final long[] rejectTimes = new long[AppOpsManager._NUM_UID_STATE];
+ return new OpEntry(op, AppOpsManager.MODE_ALLOWED, times, rejectTimes, 0 /* duration */,
+ 0 /* proxyUid */, "" /* proxyPackage */);
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
index 375b45c..96e8995 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -81,6 +81,20 @@
}
@Test
+ public void onBindViewHolder_notSetDetailsRes_barChartDetailsViewIsGoneThenReappears() {
+ // We don't call BarChartPreference#setBarChartDetails yet.
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mDetailsView.getVisibility()).isEqualTo(View.GONE);
+
+ mPreference.setBarChartDetails(R.string.debug_app);
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mDetailsView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mDetailsView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
+ }
+
+ @Test
public void setBarChartDetailsRes_setDetailsRes_showInBarChartDetails() {
mPreference.setBarChartDetails(R.string.debug_app);
mPreference.onBindViewHolder(mHolder);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index e3d3d81..526efcb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -705,8 +705,11 @@
Settings.Global.GPU_DEBUG_LAYERS_GLES,
GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES);
dumpSetting(s, p,
- Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
- GlobalSettingsProto.Gpu.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+ Settings.Global.GUP_DEV_OPT_IN_APPS,
+ GlobalSettingsProto.Gpu.GUP_DEV_OPT_IN_APPS);
+ dumpSetting(s, p,
+ Settings.Global.GUP_BLACK_LIST,
+ GlobalSettingsProto.Gpu.GUP_BLACK_LIST);
p.end(gpuToken);
final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index ce529a0..1727e75 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4125,10 +4125,12 @@
Secure.CHARGING_SOUNDS_ENABLED);
if (!globalChargingSoundEnabled.isNull()) {
- secureSettings.insertSettingLocked(
- Secure.CHARGING_SOUNDS_ENABLED,
- globalChargingSoundEnabled.getValue(), null, false,
- SettingsState.SYSTEM_PACKAGE_NAME);
+ if (secureChargingSoundsEnabled.isNull()) {
+ secureSettings.insertSettingLocked(
+ Secure.CHARGING_SOUNDS_ENABLED,
+ globalChargingSoundEnabled.getValue(), null, false,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
// set global charging_sounds_enabled setting to null since it's deprecated
globalSettings.insertSettingLocked(
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
index 0d681ed..ac97adb 100644
--- a/packages/SettingsProvider/test/Android.mk
+++ b/packages/SettingsProvider/test/Android.mk
@@ -10,7 +10,7 @@
../src/com/android/providers/settings/SettingsState.java \
../src/com/android/providers/settings/SettingsHelper.java
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
LOCAL_JAVA_LIBRARIES := android.test.base
diff --git a/packages/SettingsProvider/test/AndroidManifest.xml b/packages/SettingsProvider/test/AndroidManifest.xml
index 71e0b15..87a4f60 100644
--- a/packages/SettingsProvider/test/AndroidManifest.xml
+++ b/packages/SettingsProvider/test/AndroidManifest.xml
@@ -29,7 +29,7 @@
</application>
<instrumentation
- android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.providers.setting.test"
android:label="Settings Provider Tests" />
diff --git a/packages/SettingsProvider/test/AndroidTest.xml b/packages/SettingsProvider/test/AndroidTest.xml
index 46b8f94..9d23526 100644
--- a/packages/SettingsProvider/test/AndroidTest.xml
+++ b/packages/SettingsProvider/test/AndroidTest.xml
@@ -22,7 +22,7 @@
<option name="test-tag" value="SettingsProviderTest" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.providers.setting.test" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
index ab23af3..68efa67 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
@@ -25,9 +25,12 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
import libcore.io.Streams;
+
import org.junit.runner.RunWith;
import java.io.FileInputStream;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
index 5587cba..df4656a 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/DeviceConfigServiceTest.java
@@ -24,8 +24,9 @@
import android.os.Bundle;
import android.provider.DeviceConfig;
import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import libcore.io.Streams;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
index d8ee9b6..863b035 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/InstallNonMarketAppsDeprecationTest.java
@@ -26,10 +26,11 @@
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java
index 1074957..54f8688 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperRestoreTest.java
@@ -24,8 +24,10 @@
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
index 6fa014d..d112fac 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
@@ -17,19 +17,10 @@
package com.android.providers.settings;
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertSame;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.fail;
-
-import com.android.internal.app.LocalePicker;
-import com.android.providers.settings.SettingsHelper;
import android.os.LocaleList;
-import android.support.test.runner.AndroidJUnit4;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SystemUI/legacy/recents/res/drawable/ic_lock_to_app_24dp.xml b/packages/SystemUI/legacy/recents/res/drawable/ic_lock_to_app_24dp.xml
deleted file mode 100644
index 2d77949..0000000
--- a/packages/SystemUI/legacy/recents/res/drawable/ic_lock_to_app_24dp.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="@color/recents_task_view_lock_to_app_button_color"
- android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM12.0,17.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0c1.1,0.0 2.0,0.9 2.0,2.0S13.1,17.0 12.0,17.0zM15.1,8.0L8.9,8.0L8.9,6.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1L15.1,8.0z"/>
-</vector>
diff --git a/packages/SystemUI/legacy/recents/res/drawable/recents_freeform_workspace_bg.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_freeform_workspace_bg.xml
deleted file mode 100644
index 5f9341c..0000000
--- a/packages/SystemUI/legacy/recents/res/drawable/recents_freeform_workspace_bg.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <corners android:topLeftRadius="@dimen/recents_task_view_rounded_corners_radius"
- android:topRightRadius="@dimen/recents_task_view_rounded_corners_radius"/>
- <solid android:color="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_dark.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_dark.xml
deleted file mode 100644
index 9a060b4..0000000
--- a/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_dark.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <group
- android:translateX="-286.000000"
- android:translateY="-602.000000">
- <group
- android:translateX="109.000000"
- android:translateY="514.000000">
- <group
- android:translateX="178.000000"
- android:translateY="89.000000">
- <path
- android:strokeColor="@color/recents_task_bar_dark_icon_color"
- android:strokeWidth="2"
- android:pathData="M10,12 L10,3 L19,3 L19,5 L19,11 L19,12 L10,12 Z" />
- <path
- android:strokeColor="@color/recents_task_bar_dark_icon_color"
- android:strokeWidth="2"
- android:pathData="M15,17 L5,17 L5,7 L5,17 Z" />
- </group>
- </group>
- </group>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_light.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_light.xml
deleted file mode 100644
index b8acedb..0000000
--- a/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_light.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <group
- android:translateX="-286.000000"
- android:translateY="-602.000000">
- <group
- android:translateX="109.000000"
- android:translateY="514.000000">
- <group
- android:translateX="178.000000"
- android:translateY="89.000000">
- <path
- android:strokeColor="@color/recents_task_bar_light_icon_color"
- android:strokeWidth="2"
- android:pathData="M10,12 L10,3 L19,3 L19,5 L19,11 L19,12 L10,12 Z" />
- <path
- android:strokeColor="@color/recents_task_bar_light_icon_color"
- android:strokeWidth="2"
- android:pathData="M15,17 L5,17 L5,7 L5,17 Z" />
- </group>
- </group>
- </group>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java
new file mode 100644
index 0000000..c7bc858
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/DarkIconDispatcher.java
@@ -0,0 +1,128 @@
+/*
+ * 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.systemui.plugins;
+
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.plugins.annotations.DependsOn;
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Dispatches events to {@link DarkReceiver}s about changes in darkness, tint area and dark
+ * intensity. Accessible through {@link PluginDependency}
+ */
+@ProvidesInterface(version = DarkIconDispatcher.VERSION)
+@DependsOn(target = DarkReceiver.class)
+public interface DarkIconDispatcher {
+ int VERSION = 1;
+
+ /**
+ * Sets the dark area so {@link #applyDark} only affects the icons in the specified area.
+ *
+ * @param r the area in which icons should change its tint, in logical screen
+ * coordinates
+ */
+ void setIconsDarkArea(Rect r);
+
+ /**
+ * Adds a receiver to receive callbacks onDarkChanged
+ */
+ void addDarkReceiver(DarkReceiver receiver);
+
+ /**
+ * Adds a receiver to receive callbacks onDarkChanged
+ */
+ void addDarkReceiver(ImageView imageView);
+
+ /**
+ * Must have been previously been added through one of the addDarkReceive methods above.
+ */
+ void removeDarkReceiver(DarkReceiver object);
+
+ /**
+ * Must have been previously been added through one of the addDarkReceive methods above.
+ */
+ void removeDarkReceiver(ImageView object);
+
+ /**
+ * Used to reapply darkness on an object, must have previously been added through
+ * addDarkReceiver.
+ */
+ void applyDark(DarkReceiver object);
+
+ int DEFAULT_ICON_TINT = Color.WHITE;
+ Rect sTmpRect = new Rect();
+ int[] sTmpInt2 = new int[2];
+
+ /**
+ * @return the tint to apply to view depending on the desired tint color and
+ * the screen tintArea in which to apply that tint
+ */
+ static int getTint(Rect tintArea, View view, int color) {
+ if (isInArea(tintArea, view)) {
+ return color;
+ } else {
+ return DEFAULT_ICON_TINT;
+ }
+ }
+
+ /**
+ * @return the dark intensity to apply to view depending on the desired dark
+ * intensity and the screen tintArea in which to apply that intensity
+ */
+ static float getDarkIntensity(Rect tintArea, View view, float intensity) {
+ if (isInArea(tintArea, view)) {
+ return intensity;
+ } else {
+ return 0f;
+ }
+ }
+
+ /**
+ * @return true if more than half of the view area are in area, false
+ * otherwise
+ */
+ static boolean isInArea(Rect area, View view) {
+ if (area.isEmpty()) {
+ return true;
+ }
+ sTmpRect.set(area);
+ view.getLocationOnScreen(sTmpInt2);
+ int left = sTmpInt2[0];
+
+ int intersectStart = Math.max(left, area.left);
+ int intersectEnd = Math.min(left + view.getWidth(), area.right);
+ int intersectAmount = Math.max(0, intersectEnd - intersectStart);
+
+ boolean coversFullStatusBar = area.top <= 0;
+ boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
+ return majorityOfWidth && coversFullStatusBar;
+ }
+
+ /**
+ * Receives a callback on darkness changes
+ */
+ @ProvidesInterface(version = DarkReceiver.VERSION)
+ interface DarkReceiver {
+ int VERSION = 1;
+ void onDarkChanged(Rect area, float darkIntensity, int tint);
+ }
+}
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
deleted file mode 100644
index 73f5116..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_dismiss_outline.png b/packages/SystemUI/res/drawable-hdpi/ic_dismiss_outline.png
deleted file mode 100755
index 9afd8fa..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_dismiss_outline.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index 552a3d1..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/search_panel_scrim.xml b/packages/SystemUI/res/drawable-land/search_panel_scrim.xml
deleted file mode 100644
index 102cc9c..0000000
--- a/packages/SystemUI/res/drawable-land/search_panel_scrim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2014 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
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient
- android:type="linear"
- android:angle="180"
- android:startColor="#55000000"
- android:endColor="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
deleted file mode 100644
index 787e259..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_dismiss_outline.png b/packages/SystemUI/res/drawable-mdpi/ic_dismiss_outline.png
deleted file mode 100755
index 35737aa..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_dismiss_outline.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index 48b96d8..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/scorecard_gameover.xml b/packages/SystemUI/res/drawable-nodpi/scorecard_gameover.xml
deleted file mode 100644
index f663a66..0000000
--- a/packages/SystemUI/res/drawable-nodpi/scorecard_gameover.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- >
- <corners
- android:radius="8dp" />
- <solid
- android:color="#ffff0000" />
-</shape>
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index 23ec6db..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index e450058..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index d18e419..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index 00a751c..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp/search_panel_scrim.xml b/packages/SystemUI/res/drawable-sw600dp/search_panel_scrim.xml
deleted file mode 100644
index bbb2617..0000000
--- a/packages/SystemUI/res/drawable-sw600dp/search_panel_scrim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2014 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
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient
- android:type="linear"
- android:angle="90"
- android:startColor="#55000000"
- android:endColor="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_light_old.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_light_old.png
deleted file mode 100644
index b336ccd..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_light_old.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
deleted file mode 100644
index 6ebbc83..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_dismiss_outline.png b/packages/SystemUI/res/drawable-xhdpi/ic_dismiss_outline.png
deleted file mode 100755
index f1bfa89..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_dismiss_outline.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index e49db34..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png
deleted file mode 100644
index b91704a..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/dismiss_all_shape.xml b/packages/SystemUI/res/drawable/dismiss_all_shape.xml
deleted file mode 100644
index fb371c6..0000000
--- a/packages/SystemUI/res/drawable/dismiss_all_shape.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="17dp"
- android:width="85dp"
- android:viewportHeight="48"
- android:viewportWidth="260" >
- <group
- android:name="dismiss_all"
- android:translateX="48"
- android:translateY="6" >
- <group
- android:name="3"
- android:translateX="-24"
- android:translateY="36" >
- <path
- android:name="rectangle_path_1_2"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- <group
- android:name="2"
- android:translateX="-12"
- android:translateY="18" >
- <path
- android:name="rectangle_path_1_1"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- <group
- android:name="1" >
- <path
- android:name="rectangle_path_1"
- android:pathData="M -24.0,-6.0 l 48.0,0 l 0,12.0 l -48.0,0 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/fingerprint_icon.xml b/packages/SystemUI/res/drawable/fingerprint_icon.xml
deleted file mode 100644
index 76a86ae..0000000
--- a/packages/SystemUI/res/drawable/fingerprint_icon.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2018 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="60dp"
- android:height="60dp"
- android:viewportWidth="60"
- android:viewportHeight="60">
-
- <path
- android:fillColor="#1A73E8"
- android:fillType="evenOdd"
- android:strokeWidth="1"
- android:pathData="M 30 0 C 46.5685424949 0 60 13.4314575051 60 30 C 60 46.5685424949 46.5685424949 60 30 60 C 13.4314575051 60 0 46.5685424949 0 30 C 0 13.4314575051 13.4314575051 0 30 0 Z" />
- <group
- android:translateX="17.727273"
- android:translateY="16.363636">
- <path
- android:fillColor="#FFFFFF"
- android:strokeWidth="1"
- android:pathData="M20.3065726,3.44516129 C20.1974817,3.44516129 20.0883908,3.41788856
-19.9929362,3.36334311 C17.3747544,2.01334311 15.111118,1.44061584
-12.3974817,1.44061584 C9.69748166,1.44061584 7.1338453,2.08152493
-4.80202711,3.36334311 C4.47475439,3.54061584 4.06566348,3.41788856
-3.87475439,3.09061584 C3.69748166,2.76334311 3.82020893,2.34061584
-4.14748166,2.16334311 C6.6838453,0.786070381 9.46566348,0.0769794721
-12.3974817,0.0769794721 C15.3020271,0.0769794721 17.8383908,0.717888563
-20.6202089,2.14970674 C20.961118,2.32697947 21.0838453,2.73607038
-20.9065726,3.06334311 C20.7838453,3.30879765 20.5520271,3.44516129
-20.3065726,3.44516129 L20.3065726,3.44516129 Z M0.792936205,10.6042522
-C0.656572568,10.6042522 0.520208932,10.5633431 0.397481659,10.4815249
-C0.0838452956,10.2633431 0.0156634774,9.84061584 0.233845296,9.52697947
-C1.5838453,7.61788856 3.30202711,6.11788856 5.34748166,5.06788856
-C9.62929984,2.85879765 15.111118,2.84516129 19.4065726,5.0542522
-C21.4520271,6.1042522 23.1702089,7.59061584 24.5202089,9.48607038
-C24.7383908,9.78607038 24.6702089,10.222434 24.3565726,10.4406158
-C24.0429362,10.6587977 23.6202089,10.5906158 23.4020271,10.2769795
-C22.1747544,8.55879765 20.6202089,7.20879765 18.7792998,6.26788856
-C14.8656635,4.26334311 9.86111802,4.26334311 5.96111802,6.28152493
-C4.10657257,7.23607038 2.55202711,8.59970674 1.32475439,10.3178886
-C1.21566348,10.5087977 1.01111802,10.6042522 0.792936205,10.6042522
-L0.792936205,10.6042522 Z M9.31566348,27.0633431 C9.13839075,27.0633431
-8.96111802,26.9951613 8.83839075,26.8587977 C7.65202711,25.672434
-7.01111802,24.9087977 6.09748166,23.2587977 C5.15657257,21.5815249
-4.66566348,19.5360704 4.66566348,17.3406158 C4.66566348,13.2906158
-8.12929984,9.99061584 12.3838453,9.99061584 C16.6383908,9.99061584
-20.1020271,13.2906158 20.1020271,17.3406158 C20.1020271,17.722434
-19.8020271,18.022434 19.4202089,18.022434 C19.0383908,18.022434
-18.7383908,17.722434 18.7383908,17.3406158 C18.7383908,14.0406158
-15.8883908,11.3542522 12.3838453,11.3542522 C8.87929984,11.3542522
-6.02929984,14.0406158 6.02929984,17.3406158 C6.02929984,19.3042522
-6.46566348,21.1178886 7.29748166,22.5906158 C8.17020893,24.1587977
-8.77020893,24.8269795 9.82020893,25.8906158 C10.0792998,26.1633431
-10.0792998,26.5860704 9.82020893,26.8587977 C9.67020893,26.9951613
-9.4929362,27.0633431 9.31566348,27.0633431 Z M19.0929362,24.5406158
-C17.4702089,24.5406158 16.0383908,24.1315249 14.8656635,23.3269795
-C12.8338453,21.9497067 11.6202089,19.7133431 11.6202089,17.3406158
-C11.6202089,16.9587977 11.9202089,16.6587977 12.3020271,16.6587977
-C12.6838453,16.6587977 12.9838453,16.9587977 12.9838453,17.3406158
-C12.9838453,19.2633431 13.9656635,21.0769795 15.6292998,22.1951613
-C16.5974817,22.8497067 17.7292998,23.1633431 19.0929362,23.1633431
-C19.4202089,23.1633431 19.9656635,23.122434 20.511118,23.0269795
-C20.8792998,22.9587977 21.2338453,23.2042522 21.3020271,23.5860704
-C21.3702089,23.9542522 21.1247544,24.3087977 20.7429362,24.3769795
-C19.9656635,24.5269795 19.2838453,24.5406158 19.0929362,24.5406158
-L19.0929362,24.5406158 Z M16.3520271,27.3497067 C16.2974817,27.3497067
-16.2292998,27.3360704 16.1747544,27.322434 C14.0065726,26.722434
-12.5883908,25.9178886 11.1020271,24.4587977 C9.1929362,22.5633431
-8.1429362,20.0406158 8.1429362,17.3406158 C8.1429362,15.1315249
-10.0247544,13.3315249 12.3429362,13.3315249 C14.661118,13.3315249
-16.5429362,15.1315249 16.5429362,17.3406158 C16.5429362,18.7997067
-17.811118,19.9860704 19.3792998,19.9860704 C20.9474817,19.9860704
-22.2156635,18.7997067 22.2156635,17.3406158 C22.2156635,12.1997067
-17.7838453,8.02697947 12.3292998,8.02697947 C8.45657257,8.02697947
-4.91111802,10.1815249 3.31566348,13.522434 C2.7838453,14.6269795
-2.51111802,15.922434 2.51111802,17.3406158 C2.51111802,18.4042522
-2.60657257,20.0815249 3.42475439,22.2633431 C3.56111802,22.6178886
-3.3838453,23.0133431 3.02929984,23.1360704 C2.67475439,23.272434
-2.27929984,23.0815249 2.15657257,22.7406158 C1.48839075,20.9542522
-1.16111802,19.1815249 1.16111802,17.3406158 C1.16111802,15.7042522
-1.47475439,14.2178886 2.08839075,12.922434 C3.90202711,9.11788856
-7.92475439,6.64970674 12.3292998,6.64970674 C18.5338453,6.64970674
-23.5792998,11.4360704 23.5792998,17.3269795 C23.5792998,19.5360704
-21.6974817,21.3360704 19.3792998,21.3360704 C17.061118,21.3360704
-15.1792998,19.5360704 15.1792998,17.3269795 C15.1792998,15.8678886
-13.911118,14.6815249 12.3429362,14.6815249 C10.7747544,14.6815249
-9.50657257,15.8678886 9.50657257,17.3269795 C9.50657257,19.6587977
-10.4065726,21.8406158 12.0565726,23.4769795 C13.3520271,24.7587977
-14.5929362,25.4678886 16.5156635,25.9997067 C16.8838453,26.0951613
-17.0883908,26.4769795 16.9929362,26.8315249 C16.9247544,27.1451613
-16.6383908,27.3497067 16.3520271,27.3497067 L16.3520271,27.3497067 Z" />
- </group>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/header_dot.xml b/packages/SystemUI/res/drawable/header_dot.xml
deleted file mode 100644
index dbc6b37..0000000
--- a/packages/SystemUI/res/drawable/header_dot.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2015, 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.
--->
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval"
- android:tint="?android:attr/colorControlNormal">
-
- <solid
- android:color="#FFFFFF"/>
-
- <size
- android:width="3dp"
- android:height="3dp"/>
-</shape>
diff --git a/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml b/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml
deleted file mode 100644
index 6134b8f..0000000
--- a/packages/SystemUI/res/drawable/ic_aod_charging_24dp.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M11.0,22.98l0.0,-8.98 -4.0,0.0 6.0,-13.0 0.0,9.0 4.0,0.0z"
- android:fillColor="#ffffff"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_cast.xml b/packages/SystemUI/res/drawable/ic_cast.xml
deleted file mode 100644
index b86dfea..0000000
--- a/packages/SystemUI/res/drawable/ic_cast.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M1 18v2c0 .55 .45 1 1 1h2c0-1.66-1.34-3-3-3zm0-2.94c-.01 .51 .32 .93 .82 1.02
-2.08 .36 3.74 2 4.1 4.08 .09 .48 .5 .84 .99 .84 .61 0 1.09-.54 1-1.14a6.996
-6.996 0 0 0-5.8-5.78c-.59-.09-1.09 .38 -1.11 .98 zm0-4.03c-.01 .52 .34 .96 .85
-1.01 4.26 .43 7.68 3.82 8.1 8.08 .05 .5 .48 .88 .99 .88 .59 0 1.06-.51
-1-1.1-.52-5.21-4.66-9.34-9.87-9.85-.57-.05-1.05 .4 -1.07 .98 zM21 3H3c-1.1 0-2
-.9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_chevron_left.xml b/packages/SystemUI/res/drawable/ic_chevron_left.xml
deleted file mode 100644
index 379382b..0000000
--- a/packages/SystemUI/res/drawable/ic_chevron_left.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="36.0"
- android:viewportHeight="36.0">
-
- <path
- android:fillColor="#ffffffff"
- android:pathData="M23.1,11.1l-2.1000004,-2.1000004 -9.0,9.0 9.0,9.0 2.1000004,-2.1000004 -6.8999996,-6.8999996z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_off.xml b/packages/SystemUI/res/drawable/ic_data_off.xml
deleted file mode 100644
index b97ddae..0000000
--- a/packages/SystemUI/res/drawable/ic_data_off.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M21.6,21.6L10.8,10.9L2.1,2.1L0.8,3.4l3.3,3.3C3.1,8.2 2.5,10.0 2.5,12.0c0.0,5.2 4.3,9.5 9.5,9.5c2.0,0.0 3.8,-0.6 5.3,-1.6l3.0,3.0L21.6,21.6zM9.6,12.2l0.7,0.7L9.6,12.9L9.6,12.2zM13.9,18.6c-0.2,0.2 -0.5,0.2 -0.6,0.0l-2.4,-3.7l1.5,0.0l2.4,2.4L13.9,18.6z"
- android:fillColor="#ffffff"/>
- <path
- android:pathData="M12.0,2.5c-2.0,0.0 -3.8,0.6 -5.3,1.6l2.5,2.5L10.0,5.4c0.2,-0.2 0.5,-0.2 0.6,0.0L13.0,9.1l-1.4,0.0l2.0,2.0l0.6,0.0l0.0,0.6l5.6,5.6c1.0,-1.5 1.6,-3.3 1.6,-5.3C21.5,6.8 17.2,2.5 12.0,2.5z"
- android:fillColor="#ffffff"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_on.xml b/packages/SystemUI/res/drawable/ic_data_on.xml
deleted file mode 100644
index a65dc79..0000000
--- a/packages/SystemUI/res/drawable/ic_data_on.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M12.0,12.0m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0
- M10.6,5.4c-0.2,-0.2 -0.5,-0.2 -0.6,0.0L7.6,9.1l2.0,0.0l0.0,3.8L11.0,12.900001L11.0,9.1l2.0,0.0L10.6,5.4z
- M13.3,18.6c0.2,0.2 0.5,0.2 0.6,0.0l2.4,-3.7l-2.0,0.0l0.0,-3.8l-1.4,0.0l0.0,3.8l-2.0,0.0L13.3,18.6z"
- android:fillColor="#ffffff"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_unavailable.xml b/packages/SystemUI/res/drawable/ic_data_unavailable.xml
deleted file mode 100644
index ffb2af7..0000000
--- a/packages/SystemUI/res/drawable/ic_data_unavailable.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M15.8,12.9l3.7,0.0c0.0,-0.3 0.0,-0.6 0.0,-0.9c0.0,-5.2 -4.3,-9.5 -9.5,-9.5S0.6,6.8 0.6,12.0s4.3,9.5 9.5,9.5c2.1,0.0 4.1,-0.7 5.7,-1.9L15.8,12.9zM5.7,9.1l2.4,-3.7c0.2,-0.2 0.5,-0.2 0.6,0.0l2.4,3.7l-2.0,0.0l0.0,3.8L7.8,12.900001L7.8,9.1L5.7,9.1zM11.4,18.6L9.0,14.9l2.0,0.0l0.0,-3.8l1.4,0.0l0.0,3.8l2.0,0.0L12.0,18.6C11.9,18.8 11.6,18.8 11.4,18.6z"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M23.4,19.4l-2.1,-2.1 2.1,-2.199999 -1.1,-1.0 -2.099998,2.1 -2.1,-2.1 -1.1,1.099999 2.1,2.099999 -2.1,2.1 1.1,1.1 2.1,-2.200001 2.099998,2.200001z"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_expand_less.xml b/packages/SystemUI/res/drawable/ic_expand_less.xml
deleted file mode 100644
index e968013..0000000
--- a/packages/SystemUI/res/drawable/ic_expand_less.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="20.0dp"
- android:height="20.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M12.000000,8.000000l-6.000000,6.000000 1.400000,1.400000 4.600000,-4.599999 4.600000,4.599999 1.400000,-1.400000z"
- android:fillColor="#FF000000"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_expand_more.xml b/packages/SystemUI/res/drawable/ic_expand_more.xml
deleted file mode 100644
index 72e98ec..0000000
--- a/packages/SystemUI/res/drawable/ic_expand_more.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="20.0dp"
- android:height="20.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M16.600000,8.600000l-4.600000,4.599999 -4.600000,-4.599999 -1.400000,1.400000 6.000000,6.000000 6.000000,-6.000000z"
- android:fillColor="#FF000000"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_history.xml b/packages/SystemUI/res/drawable/ic_history.xml
deleted file mode 100644
index e936864..0000000
--- a/packages/SystemUI/res/drawable/ic_history.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
-
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89 .07 .14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7
-7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13
-21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54 .72 -1.21-3.5-2.08V8H12z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
deleted file mode 100644
index 3a47261..0000000
--- a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true"
- android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_back.xml b/packages/SystemUI/res/drawable/ic_qs_back.xml
deleted file mode 100644
index f00ba03..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_back.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M20.0,11.0L7.8,11.0l5.6,-5.6L12.0,4.0l-8.0,8.0l8.0,8.0l1.4,-1.4L7.8,13.0L20.0,13.0L20.0,11.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml
deleted file mode 100644
index 7b29740..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="32.0dp"
- android:height="32.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:pathData="M5,3
- l3.5,0 l0,-1.5 l7,0 l0,1.5 l3.5,0 l0,19.5 l-14,0z
- M10.5,8.5 l0,3 l-3,0 l0,3 l3,0 l0,3 l3,0 l0,-3 l3,0 l0,-3 l-3,0 l0,-3 z"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_lock.xml b/packages/SystemUI/res/drawable/ic_qs_lock.xml
deleted file mode 100644
index 204af7e..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_lock.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="@color/keyguard_affordance"
- android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM12.0,17.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0c1.1,0.0 2.0,0.9 2.0,2.0S13.1,17.0 12.0,17.0zM15.1,8.0L8.9,8.0L8.9,6.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1L15.1,8.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_lock_open.xml b/packages/SystemUI/res/drawable/ic_qs_lock_open.xml
deleted file mode 100644
index c877f06..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_lock_open.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="@color/keyguard_affordance"
- android:pathData="M12.0,17.0c1.1,0.0 2.0,-0.9 2.0,-2.0s-0.9,-2.0 -2.0,-2.0c-1.1,0.0 -2.0,0.9 -2.0,2.0S10.9,17.0 12.0,17.0zM18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.8 -2.2,-5.0 -5.0,-5.0C9.2,1.0 7.0,3.2 7.0,6.0l1.9,0.0c0.0,-1.7 1.4,-3.1 3.1,-3.1c1.7,0.0 3.1,1.4 3.1,3.1l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.1 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0C20.0,8.9 19.1,8.0 18.0,8.0zM18.0,20.0L6.0,20.0L6.0,10.0l12.0,0.0L18.0,20.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
deleted file mode 100644
index 7bdf50c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Placeholder icon for network logging until the real icon is finalized-->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="12.0dp"
- android:height="12.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2,24v-4h12v4H2z M2,16v-4h20v4H2z M5,7 12,0 19,7 14,7 14,15 10,15 10,7z"/>
-
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml
deleted file mode 100644
index 2974157..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_audible.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18,17v-6c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.64,5.36 6,7.92 6,11v6H4v2h10h0.38H20v-2H18zM16,17H8v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5V17z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml
deleted file mode 100644
index 6db508c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_silent.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M16,16L2.81,2.81L1.39,4.22l4.85,4.85C6.09,9.68 6,10.33 6,11v6H4v2h12.17l3.61,3.61l1.41,-1.41L16,16zM8,17c0,0 0.01,-6.11 0.01,-6.16L14.17,17H8z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12,6.5c2.49,0 4,2.02 4,4.5v2.17l2,2V11c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.72,4.86 9.05,5.2 8.46,5.63L9.93,7.1C10.51,6.73 11.2,6.5 12,6.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml
deleted file mode 100644
index c87b595..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_ringer_vibrate.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M1,9h2v6H1V9zM4,17h2V7H4V17zM21,9v6h2V9H21zM18,17h2V7h-2V17zM17,5.5v13c0,0.83 -0.67,1.5 -1.5,1.5h-7C7.67,20 7,19.33 7,18.5v-13C7,4.67 7.67,4 8.5,4h7C16.33,4 17,4.67 17,5.5zM15,6H9v12h6V6z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml
deleted file mode 100644
index 4a2bd54..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_signal_workmode_disable" >
- <target
- android:name="mask_1"
- android:animation="@anim/ic_signal_workmode_disable_mask_1_animation" />
- <target
- android:name="whole"
- android:animation="@anim/ic_signal_workmode_disable_whole_animation" />
- <target
- android:name="rectangle_path_3_position"
- android:animation="@anim/ic_signal_workmode_disable_rectangle_path_3_position_animation" />
- <target
- android:name="rectangle_path_3"
- android:animation="@anim/ic_signal_workmode_disable_rectangle_path_3_animation" />
- <target
- android:name="rectangle_path_4_position"
- android:animation="@anim/ic_signal_workmode_disable_rectangle_path_4_position_animation" />
- <target
- android:name="rectangle_path_4"
- android:animation="@anim/ic_signal_workmode_disable_rectangle_path_4_animation" />
- <target
- android:name="left"
- android:animation="@anim/ic_signal_workmode_disable_left_animation" />
- <target
- android:name="right"
- android:animation="@anim/ic_signal_workmode_disable_right_animation" />
- <target
- android:name="stick"
- android:animation="@anim/ic_signal_workmode_disable_stick_animation" />
- <target
- android:name="ic_signal_workmode_disable"
- android:animation="@anim/ic_signal_workmode_disable_stickito_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml
deleted file mode 100644
index 2d4f0b5..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="ic_signal_workmode_enable"
- android:width="42dp"
- android:viewportWidth="42"
- android:height="42dp"
- android:viewportHeight="42" >
- <group
- android:name="suitcase"
- android:translateX="21"
- android:translateY="36.9375"
- android:scaleX="0.1"
- android:scaleY="0.1" >
- <group
- android:name="suitcase_pivot"
- android:translateY="-158" >
- <clip-path
- android:name="mask_1"
- android:pathData="M 366.5,-269.5 c 0.0,0.0 -578.0,2.0 -578.0,2.0 c 0.0,0.0 480.0,480.0 480.0,480.0 c 0.0,0.0 -20.7500915527,20.75 -20.7500915527,20.75 c 0.0,0.0 -479.999908447,-480.000015259 -479.999908447,-480.000015259 c 0.0,0.0 -7.25,539.250015259 -7.25,539.250015259 c 0.0,0.0 606.0,0.0 606.0,0.0 c 0.0,0.0 0.0,-562.0 0.0,-562.0 Z" />
- <group
- android:name="whole"
- android:translateX="-1.11523"
- android:translateY="32.0918"
- android:scaleX="0"
- android:scaleY="0" >
- <path
- android:name="rectangle_path_1"
- android:strokeColor="#FFFFFFFF"
- android:strokeWidth="65"
- android:pathData="M 0.0,-66.5 l 0.0,0.0 c 36.7269358617,0.0 66.5,29.7730641383 66.5,66.5 l 0.0,0.0 c 0.0,36.7269358617 -29.7730641383,66.5 -66.5,66.5 l 0.0,0.0 c -36.7269358617,0.0 -66.5,-29.7730641383 -66.5,-66.5 l 0.0,0.0 c 0.0,-36.7269358617 29.7730641383,-66.5 66.5,-66.5 Z" />
- </group>
- <group
- android:name="handle"
- android:translateY="-100" >
- <path
- android:name="rectangle_path_2"
- android:strokeColor="#FFFFFFFF"
- android:strokeWidth="35"
- android:pathData="M -34.0,-50.0 l 68.0,0.0 c 8.8365559968,0.0 16.0,7.1634440032 16.0,16.0 l 0.0,68.0 c 0.0,8.8365559968 -7.1634440032,16.0 -16.0,16.0 l -68.0,0.0 c -8.8365559968,0.0 -16.0,-7.1634440032 -16.0,-16.0 l 0.0,-68.0 c 0.0,-8.8365559968 7.1634440032,-16.0 16.0,-16.0 Z" />
- </group>
- <group
- android:name="case"
- android:translateY="32.68518" >
- <group
- android:name="case_pivot"
- android:translateY="-32.68518" >
- <group
- android:name="bottom"
- android:translateY="-97.62964" >
- <group
- android:name="bottom_pivot"
- android:translateY="40" >
- <group
- android:name="rectangle_path_3_position"
- android:translateY="25" >
- <path
- android:name="rectangle_path_3"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" />
- </group>
- </group>
- </group>
- <group
- android:name="top"
- android:translateY="163" >
- <group
- android:name="top_pivot"
- android:translateY="-40" >
- <group
- android:name="rectangle_path_4_position"
- android:translateY="-25" >
- <path
- android:name="rectangle_path_4"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -143.0,-65.0 l 286.0,0.0 c 17.6731119936,0.0 32.0,14.3268880064 32.0,32.0 l 0.0,66.0 c 0.0,17.6731119936 -14.3268880064,32.0 -32.0,32.0 l -286.0,0.0 c -17.6731119936,0.0 -32.0,-14.3268880064 -32.0,-32.0 l 0.0,-66.0 c 0.0,-17.6731119936 14.3268880064,-32.0 32.0,-32.0 Z" />
- </group>
- </group>
- </group>
- <group
- android:name="left"
- android:translateX="-175.00635"
- android:translateY="30"
- android:scaleX="1.8" >
- <group
- android:name="left_pivot"
- android:translateX="50.00635" >
- <path
- android:name="rectangle_path_5"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -50.0,-88.0 l 100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
- </group>
- </group>
- <group
- android:name="right"
- android:translateX="174.97778"
- android:translateY="30"
- android:scaleX="1.8" >
- <group
- android:name="right_pivot"
- android:translateX="-49.97778" >
- <path
- android:name="rectangle_path_6"
- android:fillColor="#FFFFFFFF"
- android:pathData="M -50.0,-88.0 l 100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l -100.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-176.0 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
- </group>
- </group>
- </group>
- </group>
- <group
- android:name="stick"
- android:translateX="-166.59082"
- android:translateY="-156.51367"
- android:rotation="-45" >
- <group
- android:name="stick_pivot"
- android:translateX="0.18161"
- android:translateY="243.8158" >
- <path
- android:name="stickito"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1"
- android:pathData="M -16.5,-243.999885 l 33.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,487.99977 c 0.0,0.0 0.0,0.0 0.0,0.0 l -33.0,0.0 c 0.0,0.0 0.0,0.0 0.0,0.0 l 0.0,-487.99977 c 0.0,0.0 0.0,0.0 0.0,0.0 Z" />
- </group>
- </group>
- </group>
- </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml
deleted file mode 100644
index c98f800..0000000
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/ic_signal_workmode_enable" >
- <target
- android:name="mask_1"
- android:animation="@anim/ic_signal_workmode_enable_mask_1_animation" />
- <target
- android:name="whole"
- android:animation="@anim/ic_signal_workmode_enable_whole_animation" />
- <target
- android:name="rectangle_path_3_position"
- android:animation="@anim/ic_signal_workmode_enable_rectangle_path_3_position_animation" />
- <target
- android:name="rectangle_path_3"
- android:animation="@anim/ic_signal_workmode_enable_rectangle_path_3_animation" />
- <target
- android:name="rectangle_path_4_position"
- android:animation="@anim/ic_signal_workmode_enable_rectangle_path_4_position_animation" />
- <target
- android:name="rectangle_path_4"
- android:animation="@anim/ic_signal_workmode_enable_rectangle_path_4_animation" />
- <target
- android:name="left"
- android:animation="@anim/ic_signal_workmode_enable_left_animation" />
- <target
- android:name="right"
- android:animation="@anim/ic_signal_workmode_enable_right_animation" />
- <target
- android:name="stick"
- android:animation="@anim/ic_signal_workmode_enable_stick_animation" />
- <target
- android:name="ic_signal_workmode_enable"
- android:animation="@anim/ic_signal_workmode_enable_stickito_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_sim.xml b/packages/SystemUI/res/drawable/ic_sim.xml
deleted file mode 100644
index a9a1902..0000000
--- a/packages/SystemUI/res/drawable/ic_sim.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,2h-8L4,8v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C20,2.9 19.1,2 18,2zM18,4v16H6V8.83L10.83,4L18,4L18,4z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M7,17h2v2h-2z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M15,17h2v2h-2z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M7,11h2v4h-2z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M11,15h2v4h-2z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M11,11h2v2h-2z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M15,11h2v4h-2z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_speaker.xml b/packages/SystemUI/res/drawable/ic_speaker.xml
deleted file mode 100644
index 1ea293c..0000000
--- a/packages/SystemUI/res/drawable/ic_speaker.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal" >
- <path
- android:pathData="M17,2L7,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,1.99 2,1.99L17,22c1.1,0 2,-0.9 2,-2L19,4c0,-1.1 -0.9,-2 -2,-2zM12,4c1.1,0 2,0.9 2,2s-0.9,2 -2,2c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2zM12,20c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"
- android:fillColor="#FFFFFFFF"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_speaker_group.xml b/packages/SystemUI/res/drawable/ic_speaker_group.xml
deleted file mode 100644
index d6867d7..0000000
--- a/packages/SystemUI/res/drawable/ic_speaker_group.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal" >
- <path
- android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
- android:fillColor="#FFFFFFFF"/>
- <path
- android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
- android:fillColor="#FFFFFFFF"/>
- <path
- android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
- android:fillColor="#FFFFFFFF"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_swap.xml b/packages/SystemUI/res/drawable/ic_swap.xml
deleted file mode 100644
index 30da2a9..0000000
--- a/packages/SystemUI/res/drawable/ic_swap.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- Copyright (C) 2018 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorForeground">
- <path
- android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z"
- android:fillColor="#FFFFFF"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_tv.xml b/packages/SystemUI/res/drawable/ic_tv.xml
deleted file mode 100644
index cc2ae91..0000000
--- a/packages/SystemUI/res/drawable/ic_tv.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal" >
- <path
- android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"
- android:fillColor="#FFFFFFFF"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_zen_all.xml b/packages/SystemUI/res/drawable/ic_zen_all.xml
deleted file mode 100644
index 5df2447..0000000
--- a/packages/SystemUI/res/drawable/ic_zen_all.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="18dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M6.6,3.6L5.2,2.2C2.8,4.0 1.2,6.8 1.0,10.0l2.0,0.0C3.2,7.3 4.5,5.0 6.6,3.6zM20.0,10.0l2.0,0.0c-0.2,-3.2 -1.7,-6.0 -4.1,-7.8l-1.4,1.4C18.5,5.0 19.8,7.3 20.0,10.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0l-2.0,-2.0L18.0,10.5zM11.5,22.0c0.1,0.0 0.3,0.0 0.4,0.0c0.7,-0.1 1.2,-0.6 1.4,-1.2c0.1,-0.2 0.2,-0.5 0.2,-0.8l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_zen_important.xml b/packages/SystemUI/res/drawable/ic_zen_important.xml
deleted file mode 100644
index c2a59b8..0000000
--- a/packages/SystemUI/res/drawable/ic_zen_important.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="18dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.0,17.273l6.1800003,3.7269993 -1.6350002,-7.0290003 5.455,-4.7269993 -7.191,-0.6170006 -2.809,-6.627 -2.809,6.627 -7.191,0.6170006 5.455,4.7269993 -1.6349998,7.0290003z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_zen_none.xml b/packages/SystemUI/res/drawable/ic_zen_none.xml
deleted file mode 100644
index 99014f2..0000000
--- a/packages/SystemUI/res/drawable/ic_zen_none.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18dp"
- android:height="18dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M24.0,4.0C13.0,4.0 4.0,13.0 4.0,24.0c0.0,11.0 9.0,20.0 20.0,20.0c11.0,0.0 20.0,-9.0 20.0,-20.0C44.0,13.0 35.0,4.0 24.0,4.0zM24.0,40.0c-8.8,0.0 -16.0,-7.2 -16.0,-16.0c0.0,-3.7 1.3,-7.1 3.4,-9.8l22.4,22.4C31.1,38.7 27.7,40.0 24.0,40.0zM36.6,33.8L14.2,11.4C16.9,9.3 20.3,8.0 24.0,8.0c8.8,0.0 16.0,7.2 16.0,16.0C40.0,27.7 38.7,31.1 36.6,33.8z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml b/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
deleted file mode 100644
index b812d43..0000000
--- a/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2014 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
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="#1a000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/notification_expand_more.xml b/packages/SystemUI/res/drawable/notification_expand_more.xml
deleted file mode 100644
index 430fb0d..0000000
--- a/packages/SystemUI/res/drawable/notification_expand_more.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2015 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._more
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="22.0dp"
- android:height="22.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M16.600000,8.600000l-4.600000,4.599999 -4.600000,-4.599999 -1.400000,1.400000 6.000000,6.000000 6.000000,-6.000000z"
- android:fillColor="#FF000000"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pip_dismiss.xml b/packages/SystemUI/res/drawable/pip_dismiss.xml
deleted file mode 100644
index f656eeb..0000000
--- a/packages/SystemUI/res/drawable/pip_dismiss.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="42.0dp"
- android:height="42.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M38.000000,12.800000l-2.799999,-2.800000 -11.200001,11.200001 -11.200000,-11.200001 -2.800000,2.800000 11.200001,11.200000 -11.200001,11.200001 2.800000,2.799999 11.200000,-11.200001 11.200001,11.200001 2.799999,-2.799999 -11.200001,-11.200001z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_notification_icon.xml b/packages/SystemUI/res/drawable/pip_notification_icon.xml
deleted file mode 100644
index 592bc60..0000000
--- a/packages/SystemUI/res/drawable/pip_notification_icon.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/>
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pop_ball.xml b/packages/SystemUI/res/drawable/pop_ball.xml
deleted file mode 100644
index ee1220f..0000000
--- a/packages/SystemUI/res/drawable/pop_ball.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M0,50 a50,50 0 1 1 100,0
- a50,50 0 1 1 -100,0"
- android:fillColor="#FFFF1744"/>
- <path
- android:pathData="M16,36 A24,24 0 1 1 64,36
- M64,36 A24,24 0 1 1 16,36"
- android:fillColor="#20FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_belt.xml b/packages/SystemUI/res/drawable/pop_belt.xml
deleted file mode 100644
index e0ea575..0000000
--- a/packages/SystemUI/res/drawable/pop_belt.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000m-47.599998,0.000000a47.599998,47.599998 0.000000,1.000000 1.000000,95.199997 0.000000a47.599998,47.599998 0.000000,1.000000 1.000000,-95.199997 0.000000"
- android:fillColor="#9C27B0"/>
- <path
- android:pathData="M50.000000,2.429000c-26.337999,0.000000 -47.688999,21.351000 -47.688999,47.688999c0.000000,13.168000 5.337000,25.091000 13.968000,33.722000l67.444000,-67.443001C75.092003,7.766000 63.168999,2.429000 50.000000,2.429000z"
- android:fillColor="#BA68C8"/>
- <path
- android:pathData="M0.000000,41.573002l100.000000,0.000000l0.000000,17.090000l-100.000000,0.000000z"
- android:fillColor="#9C27B0"/>
- <path
- android:pathData="M0.000000,58.662998l0.000000,-17.089996 100.000000,0.000000z"
- android:fillColor="#BA68C8"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_droid.xml b/packages/SystemUI/res/drawable/pop_droid.xml
deleted file mode 100644
index eed325c..0000000
--- a/packages/SystemUI/res/drawable/pop_droid.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000m-50.000000,0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,100.000000 0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,-100.000000 0.000000"
- android:fillColor="#9E9D24"/>
- <path
- android:pathData="M30.775999,24.528000m-4.209000,0.000000a4.209000,4.209000 0.000000,1.000000 1.000000,8.418000 0.000000a4.209000,4.209000 0.000000,1.000000 1.000000,-8.418000 0.000000"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M69.226997,24.528000m-4.210000,0.000000a4.210000,4.210000 0.000000,1.000000 1.000000,8.420000 0.000000a4.210000,4.210000 0.000000,1.000000 1.000000,-8.420000 0.000000"
- android:fillColor="#FFFFFF"/>
- <path
- android:pathData="M85.352997,14.648000C65.829002,-4.877000 34.168999,-4.877000 14.646000,14.646000C4.882000,24.410000 0.002000,37.207001 0.000000,50.000999l99.996002,0.002000C99.996002,37.207001 95.115997,24.410000 85.352997,14.648000z"
- android:fillColor="#C0CA33"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_pizza.xml b/packages/SystemUI/res/drawable/pop_pizza.xml
deleted file mode 100644
index 1806b5a..0000000
--- a/packages/SystemUI/res/drawable/pop_pizza.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M14.645000,14.645000C5.597000,23.693001 0.000000,36.193001 0.000000,50.000000l50.000000,0.000000L14.645000,14.645000z"
- android:fillColor="#2979FF"/>
- <path
- android:pathData="M100.000000,50.000000c0.000000,-13.807000 -5.597000,-26.306999 -14.645000,-35.355000L50.000000,50.000000L100.000000,50.000000z"
- android:fillColor="#FF1744"/>
- <path
- android:pathData="M85.355003,14.645000C76.306999,5.597000 63.806999,0.000000 50.000000,0.000000l0.000000,50.000000L85.355003,14.645000z"
- android:fillColor="#0F9D58"/>
- <path
- android:pathData="M50.000000,0.000000C36.193001,0.000000 23.693001,5.597000 14.645000,14.645000L50.000000,50.000000L50.000000,0.000000z"
- android:fillColor="#FFBC00"/>
- <path
- android:pathData="M50.000000,50.000000l35.355000,35.355000C94.403000,76.307999 100.000000,63.807999 100.000000,50.000000L50.000000,50.000000z"
- android:fillColor="#2979FF"/>
- <path
- android:pathData="M50.000000,100.000000c13.807000,0.000000 26.306999,-5.596000 35.355000,-14.645000L50.000000,50.000000L50.000000,100.000000z"
- android:fillColor="#FFBC00"/>
- <path
- android:pathData="M14.645000,85.355003C23.693001,94.403999 36.193001,100.000000 50.000000,100.000000L50.000000,50.000000L14.645000,85.355003z"
- android:fillColor="#0F9D58"/>
- <path
- android:pathData="M0.000000,50.000000c0.000000,13.808000 5.597000,26.308001 14.645000,35.355000L50.000000,50.000000L0.000000,50.000000z"
- android:fillColor="#FF1744"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_stripes.xml b/packages/SystemUI/res/drawable/pop_stripes.xml
deleted file mode 100644
index ef6c8e8..0000000
--- a/packages/SystemUI/res/drawable/pop_stripes.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000m-50.000000,0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,100.000000 0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,-100.000000 0.000000"
- android:fillColor="#F57C00"/>
- <path
- android:pathData="M50.000999,100.000000c14.136000,0.000000 26.893000,-5.876000 35.987000,-15.308000L14.013000,84.692001C23.106001,94.124001 35.862999,100.000000 50.000999,100.000000z"
- android:fillColor="#E65100"/>
- <path
- android:pathData="M50.000999,0.000000C35.862999,0.000000 23.106001,5.876000 14.013000,15.308000l71.974998,0.000000C76.893997,5.876000 64.137001,0.000000 50.000999,0.000000z"
- android:fillColor="#FFA726"/>
- <path
- android:pathData="M96.501999,31.631001c-2.423000,-6.127000 -6.020000,-11.660000 -10.514000,-16.323000L14.013000,15.308001C9.517000,19.971001 5.922000,25.503000 3.499000,31.631001L96.501999,31.631001z"
- android:fillColor="#FB8C00"/>
- <path
- android:pathData="M3.499000,68.370003c2.423000,6.128000 6.018000,11.658000 10.514000,16.322001l71.974998,0.000000c4.494000,-4.664000 8.091000,-10.194000 10.514000,-16.322001L3.499000,68.370003z"
- android:fillColor="#EF6C00"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_swirl.xml b/packages/SystemUI/res/drawable/pop_swirl.xml
deleted file mode 100644
index f87569b..0000000
--- a/packages/SystemUI/res/drawable/pop_swirl.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000C86.898003,27.834999 79.244003,11.688000 76.177002,7.399000c-7.240000,-4.459000 -15.703000,-7.112000 -24.770000,-7.363000C56.247002,2.253000 70.815002,12.456000 50.000000,50.000000z"
- android:fillColor="#FFFFFA"/>
- <path
- android:pathData="M50.000000,50.000000c20.815001,-37.543999 6.247000,-47.747002 1.407000,-49.964001C50.938000,0.022000 50.472000,0.000000 50.000000,0.000000c-8.627000,0.000000 -16.743999,2.186000 -23.827000,6.032000C31.392000,5.514000 49.251999,6.903000 50.000000,50.000000z"
- android:fillColor="#76FF03"/>
- <path
- android:pathData="M50.000000,50.000000c37.543999,20.816000 47.747002,6.248000 49.965000,1.408000C99.977997,50.938000 100.000000,50.473000 100.000000,50.000000c0.000000,-8.627000 -2.186000,-16.743999 -6.032000,-23.827000C94.486000,31.393000 93.098000,49.251999 50.000000,50.000000z"
- android:fillColor="#76FF03"/>
- <path
- android:pathData="M50.000000,50.000000c43.098000,-0.748000 44.486000,-18.607000 43.967999,-23.827000c-4.186000,-7.708000 -10.344000,-14.188000 -17.791000,-18.773001C79.244003,11.688000 86.898003,27.834999 50.000000,50.000000z"
- android:fillColor="#303F9F"/>
- <path
- android:pathData="M50.000000,50.000000C27.834000,13.103000 11.687000,20.757000 7.398000,23.823999C2.940000,31.063000 0.287000,39.527000 0.035000,48.592999C2.253000,43.752998 12.456000,29.184999 50.000000,50.000000z"
- android:fillColor="#FFFFFA"/>
- <path
- android:pathData="M50.000000,50.000000C49.251999,6.903000 31.392000,5.514000 26.173000,6.032000c-7.709000,4.187000 -14.188000,10.344000 -18.774000,17.792000C11.687000,20.757000 27.834000,13.103000 50.000000,50.000000z"
- android:fillColor="#303F9F"/>
- <path
- android:pathData="M50.000000,50.000000C12.456000,29.184999 2.253000,43.752998 0.035000,48.592999C0.022000,49.062000 0.000000,49.528000 0.000000,50.000000c0.000000,8.628000 2.186000,16.743999 6.032000,23.827999C5.514000,68.609001 6.902000,50.749001 50.000000,50.000000z"
- android:fillColor="#76FF03"/>
- <path
- android:pathData="M50.000000,50.000000c0.748000,43.098000 18.608000,44.486000 23.827000,43.969002c7.709000,-4.187000 14.188000,-10.344000 18.774000,-17.791000C88.313004,79.244003 72.166000,86.898003 50.000000,50.000000z"
- android:fillColor="#303F9F"/>
- <path
- android:pathData="M50.000000,50.000000c22.166000,36.897999 38.313000,29.243999 42.602001,26.177999c4.458000,-7.240000 7.111000,-15.703000 7.363000,-24.770000C97.747002,56.248001 87.543999,70.816002 50.000000,50.000000z"
- android:fillColor="#FFFFFA"/>
- <path
- android:pathData="M50.000000,50.000000c-20.815001,37.544998 -6.247000,47.748001 -1.407000,49.965000C49.062000,99.978996 49.528000,100.000000 50.000000,100.000000c8.627000,0.000000 16.743999,-2.185000 23.827000,-6.031000C68.608002,94.486000 50.748001,93.098000 50.000000,50.000000z"
- android:fillColor="#76FF03"/>
- <path
- android:pathData="M50.000000,50.000000C13.103000,72.166000 20.757000,88.313004 23.823000,92.601997c7.240000,4.459000 15.703000,7.112000 24.770000,7.363000C43.752998,97.748001 29.184999,87.544998 50.000000,50.000000z"
- android:fillColor="#FFFFFA"/>
- <path
- android:pathData="M50.000000,50.000000C6.902000,50.749001 5.514000,68.609001 6.032000,73.828003c4.186000,7.708000 10.344000,14.188000 17.791000,18.773001C20.757000,88.313004 13.103000,72.166000 50.000000,50.000000z"
- android:fillColor="#303F9F"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_vortex.xml b/packages/SystemUI/res/drawable/pop_vortex.xml
deleted file mode 100644
index 2380e68..0000000
--- a/packages/SystemUI/res/drawable/pop_vortex.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000m-50.000000,0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,100.000000 0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,-100.000000 0.000000"
- android:fillColor="#F8F8FF"/>
- <path
- android:pathData="M58.658001,89.648003c-19.330000,0.000000 -35.000000,-15.670000 -35.000000,-35.000000c0.000000,-13.531000 10.969000,-24.500000 24.500000,-24.500000c9.472000,0.000000 17.150000,7.679000 17.150000,17.150000c0.000000,6.631000 -5.375000,12.006000 -12.006000,12.006000c-3.798000,0.000000 -7.004000,-2.522000 -8.045000,-5.982000c1.021000,1.136000 2.497000,1.854000 4.145000,1.854000c2.644000,0.000000 4.853000,-1.841000 5.428000,-4.310000c0.175000,-0.558000 0.271000,-1.150000 0.271000,-1.766000c0.000000,-4.642000 -3.763000,-8.404000 -8.403000,-8.404000c-6.631000,0.000000 -12.006000,5.375000 -12.006000,12.006000c0.000000,9.472000 7.679000,17.149000 17.150000,17.149000c13.531000,0.000000 24.500000,-10.969000 24.500000,-24.500000c0.000000,-19.330000 -15.670000,-35.000000 -35.000000,-35.000000c-12.963000,0.000000 -24.773001,4.935000 -33.657001,13.025000C2.824000,31.087000 0.000000,40.212002 0.000000,50.000000c0.000000,27.615000 22.386000,50.000000 50.000000,50.000000c17.825001,0.000000 33.462002,-9.335000 42.313999,-23.375999C83.431000,84.714996 71.621002,89.648003 58.658001,89.648003z"
- android:fillColor="#7BAAF7"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/pop_vortex2.xml b/packages/SystemUI/res/drawable/pop_vortex2.xml
deleted file mode 100644
index 0a96b74..0000000
--- a/packages/SystemUI/res/drawable/pop_vortex2.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="100.0dp"
- android:height="100.0dp"
- android:viewportWidth="100.0"
- android:viewportHeight="100.0">
- <path
- android:pathData="M50.000000,50.000000m-50.000000,0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,100.000000 0.000000a50.000000,50.000000 0.000000,1.000000 1.000000,-100.000000 0.000000"
- android:fillColor="#D81B60"/>
- <path
- android:pathData="M21.250000,78.369003c-13.200000,-16.000000 -10.930000,-39.671001 5.070000,-52.870998c12.799000,-10.560000 31.737000,-8.743000 42.294998,4.057000c8.448000,10.239000 6.996000,25.389000 -3.244000,33.837002c-8.191000,6.759000 -20.311001,5.596000 -27.068001,-2.596000c-5.408000,-6.554000 -4.478000,-16.249001 2.076000,-21.656000c5.242000,-4.325000 12.998000,-3.581000 17.323999,1.661000c3.460000,4.194000 2.865000,10.399000 -1.330000,13.859000c-3.354000,2.769000 -8.318000,2.293000 -11.087000,-1.062000c-2.214000,-2.685000 -1.833000,-6.655000 0.851000,-8.870000c2.147000,-1.771000 5.324000,-1.468000 7.096000,0.681000c1.393000,1.688000 1.174000,4.165000 -0.464000,5.596000c0.409000,-0.564000 0.657000,-1.253000 0.657000,-2.004000c0.000000,-1.021000 -0.455000,-1.928000 -1.165000,-2.556000c-0.067000,-0.112000 -0.134000,-0.226000 -0.220000,-0.329000c-1.135000,-1.373000 -3.168000,-1.568000 -4.542000,-0.435000c-1.719000,1.417000 -1.962000,3.958000 -0.544000,5.677000c1.771000,2.146000 4.949000,2.451000 7.096000,0.680000c2.684000,-2.215000 3.064000,-6.186000 0.851000,-8.870000c-2.769000,-3.356000 -7.732000,-3.831000 -11.087000,-1.063000c-4.195000,3.460000 -4.790000,9.665000 -1.330000,13.859000c4.326000,5.244000 12.082000,5.987000 17.323999,1.662000c6.554000,-5.407000 7.484000,-15.102000 2.076000,-21.656000c-6.758000,-8.191000 -18.875999,-9.354000 -27.069000,-2.596000c-10.239000,8.448000 -11.691000,23.598000 -3.244000,33.837002c10.560000,12.800000 29.497000,14.616000 42.296001,4.056000c16.000000,-13.199000 18.270000,-36.869999 5.070000,-52.868999C68.397003,5.620000 52.516998,-0.139000 37.205002,1.659000c-8.665000,2.287000 -16.410999,6.836000 -22.561001,12.985000C5.597000,23.693001 0.000000,36.193001 0.000000,50.000000c0.000000,13.808000 5.597000,26.308001 14.645000,35.355000C23.693001,94.403999 36.193001,100.000000 50.000000,100.000000c11.935000,0.000000 22.886999,-4.187000 31.482000,-11.164000C61.909000,100.523003 36.202999,96.495003 21.250000,78.369003z"
- android:fillColor="#F06292"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_subhead_caret.xml b/packages/SystemUI/res/drawable/qs_subhead_caret.xml
deleted file mode 100644
index 13a168d..0000000
--- a/packages/SystemUI/res/drawable/qs_subhead_caret.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path
- android:fillColor="@color/qs_subhead"
- android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_tile_background.xml b/packages/SystemUI/res/drawable/qs_tile_background.xml
deleted file mode 100644
index 96891c1..0000000
--- a/packages/SystemUI/res/drawable/qs_tile_background.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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.
-*/
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true">
- <color android:color="#212121" />
- </item>
- <item>
- <color android:color="#161616" />
- </item>
-</selector>
diff --git a/packages/SystemUI/res/drawable/quick_header_bg.xml b/packages/SystemUI/res/drawable/quick_header_bg.xml
deleted file mode 100644
index 920e6f5..0000000
--- a/packages/SystemUI/res/drawable/quick_header_bg.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2015 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
- -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight" >
- <item android:drawable="?android:attr/colorPrimary"/>
-</ripple>
diff --git a/packages/SystemUI/res/drawable/scorecard_gameover.xml b/packages/SystemUI/res/drawable/scorecard_gameover.xml
deleted file mode 100644
index f663a66..0000000
--- a/packages/SystemUI/res/drawable/scorecard_gameover.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- >
- <corners
- android:radius="8dp" />
- <solid
- android:color="#ffff0000" />
-</shape>
diff --git a/packages/SystemUI/res/drawable/stat_notify_more.xml b/packages/SystemUI/res/drawable/stat_notify_more.xml
deleted file mode 100644
index 50f1286..0000000
--- a/packages/SystemUI/res/drawable/stat_notify_more.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M22.000000,3.000000L7.000000,3.000000C6.300000,3.000000 5.800000,3.400000 5.400000,3.900000L0.000000,12.000000l5.400000,8.100000c0.400000,0.500000 1.000000,0.900000 1.700000,0.900000L22.000000,21.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L24.000000,5.000000C24.000000,3.900000 23.100000,3.000000 22.000000,3.000000zM9.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S9.800000,13.500000 9.000000,13.500000zM14.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S14.800000,13.500000 14.000000,13.500000zM19.000000,13.500000c-0.800000,0.000000 -1.500000,-0.700000 -1.500000,-1.500000s0.700000,-1.500000 1.500000,-1.500000c0.800000,0.000000 1.500000,0.700000 1.500000,1.500000S19.799999,13.500000 19.000000,13.500000z"
- android:fillColor="#FFFFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_auto_rotate_landscape.xml b/packages/SystemUI/res/drawable/stat_sys_auto_rotate_landscape.xml
deleted file mode 100644
index ba0709e..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_auto_rotate_landscape.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="2.5dp"
- android:insetRight="2.5dp">
- <vector
- android:height="17dp"
- android:width="17dp"
- android:viewportHeight="48"
- android:viewportWidth="48" >
- <group
- android:name="ic_screen_rotation_48px_outlines"
- android:translateX="24"
- android:translateY="24" >
- <group
- android:name="ic_screen_rotation_48px_outlines_pivot"
- android:translateX="-24.15"
- android:translateY="-24.25" >
- <group
- android:name="arrows"
- android:translateX="24.1"
- android:translateY="24.1" >
- <group
- android:name="arrows_pivot"
- android:translateX="-24.1"
- android:translateY="-24.1" >
- <path
- android:name="arrow_top"
- android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- <path
- android:name="arrow_bottom"
- android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
- <group
- android:name="device"
- android:translateX="24.14999"
- android:translateY="24.25" >
- <path
- android:name="body"
- android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
- </group>
- </vector>
-</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_auto_rotate_portrait.xml b/packages/SystemUI/res/drawable/stat_sys_auto_rotate_portrait.xml
deleted file mode 100644
index 46a1f35..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_auto_rotate_portrait.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetLeft="2.5dp"
- android:insetRight="2.5dp">
- <vector
- android:height="17dp"
- android:width="17dp"
- android:viewportHeight="48"
- android:viewportWidth="48" >
- <group
- android:name="icon"
- android:translateX="24"
- android:translateY="24" >
- <group
- android:name="icon_pivot"
- android:translateX="-24.15"
- android:translateY="-24.25" >
- <group
- android:name="arrows"
- android:translateX="24.1"
- android:translateY="24.1" >
- <group
- android:name="arrows_pivot"
- android:translateX="-24.1"
- android:translateY="-24.1" >
- <path
- android:name="arrow_top"
- android:pathData="M 33.1499938965,5.25 c 6.5,3.10000610352 11.1999969482,9.40000915527 11.8999938965,17.0 c 0.0,0.0 3.00001525879,0.0 3.00001525879,0.0 c -1.00001525879,-12.3000030518 -11.3000030518,-22.0 -23.9000091553,-22.0 c -0.399993896484,0.0 -0.899993896484,0.0 -1.30000305176,0.100006103516 c 0.0,0.0 7.60000610352,7.59999084473 7.60000610352,7.59999084473 c 0.0,0.0 2.69999694824,-2.69999694824 2.69999694824,-2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- <path
- android:name="arrow_bottom"
- android:pathData="M 15.1499938965,43.25 c -6.5,-3.09999084473 -11.1999969482,-9.5 -11.8999938965,-17.0 c 0.0,0.0 -3.0,0.0 -3.0,0.0 c 1.0,12.3000030518 11.299987793,22.0 23.8999938965,22.0 c 0.399993896484,0.0 0.899993896484,0.0 1.30000305176,-0.0999908447266 c 0.0,0.0 -7.60000610352,-7.60000610352 -7.60000610352,-7.60000610352 c 0.0,0.0 -2.69999694824,2.69999694824 -2.69999694824,2.69999694824 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
- <group
- android:name="device"
- android:translateX="24.14999"
- android:translateY="24.25" >
- <path
- android:name="device_1"
- android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
- android:fillColor="#FFFFFFFF"
- android:fillAlpha="1" />
- </group>
- </group>
- </group>
- </vector>
-</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status_off.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status_off.xml
deleted file mode 100644
index 1dedd5d..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status_off.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="23dp"
- android:height="18dp"
- android:viewportWidth="23.0"
- android:viewportHeight="18.0">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M19.4,16.6l-1.1,-1.1L8,5L5.1,2.2L4.2,3.1l2,2H5.7c-0.8,0 -1.4,0.6 -1.4,1.4v8c0,0.8 0.6,1.4 1.4,1.4h11.4l1.5,1.5L19.4,16.6zM18.7,6.5c0,-0.8 -0.6,-1.4 -1.4,-1.4h-2.9V3.6c0,-0.8 -0.6,-1.4 -1.4,-1.4h-3C9.2,2.1 8.6,2.8 8.6,3.6v0.2L18.7,14C18.7,14 18.7,6.5 18.7,6.5zM12.9,5.1H10V3.6h2.9V5.1z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml b/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
deleted file mode 100644
index 5c9be5c..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_in.xml b/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
deleted file mode 100644
index 7e6e09b..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_in.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:name="in"
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml b/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
deleted file mode 100644
index b7b6f0f..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_inout.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:name="in"
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.7,12.2l-2.0,3.5l-2.0,-3.5z" />
- <path
- android:name="out"
- android:fillColor="#FFFFFFFF"
- android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_out.xml b/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
deleted file mode 100644
index 910c035..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_out.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:name="out"
- android:fillColor="#FFFFFFFF"
- android:pathData="M0.5,15.7l2.0,-3.5l2.0,3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
deleted file mode 100644
index ba3d4e6..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_in.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="16.25dp"
- android:height="15dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
- <path
- android:name="in"
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
deleted file mode 100644
index 1f3b68f..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_inout.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="16.25dp"
- android:height="15dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
- <path
- android:name="in"
- android:fillColor="#FFFFFFFF"
- android:pathData="M8.7,18.3l-2.0,3.5l-2.0,-3.5z" />
- <path
- android:name="out"
- android:fillColor="#FFFFFFFF"
- android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
deleted file mode 100644
index 24c6b1e..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_out.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true"
- android:width="16.25dp"
- android:height="15dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
- <path
- android:name="out"
- android:fillColor="#FFFFFFFF"
- android:pathData="M0.5,21.8l2.0,-3.5l2.0,3.5z" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/sun2.xml b/packages/SystemUI/res/drawable/sun2.xml
deleted file mode 100644
index 6d2d504..0000000
--- a/packages/SystemUI/res/drawable/sun2.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48.0dp"
- android:height="48.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:pathData="M40.000000,17.400000L40.000000,8.000000l-9.400000,0.000000L24.000000,1.400000L17.400000,8.000000L8.000000,8.000000l0.000000,9.400000L1.400000,24.000000L8.000000,30.600000L8.000000,40.000000l9.400000,0.000000l6.600000,6.600000l6.600000,-6.600000L40.000000,40.000000l0.000000,-9.400000l6.600000,-6.600000L40.000000,17.400000zM24.000000,36.000000c-6.600000,0.000000 -12.000000,-5.400000 -12.000000,-12.000000s5.400000,-12.000000 12.000000,-12.000000c6.600000,0.000000 12.000000,5.400000 12.000000,12.000000S30.600000,36.000000 24.000000,36.000000zM24.000000,16.000000c-4.400000,0.000000 -8.000000,3.600000 -8.000000,8.000000c0.000000,4.400000 3.600000,8.000000 8.000000,8.000000s8.000000,-3.600000 8.000000,-8.000000C32.000000,19.600000 28.400000,16.000000 24.000000,16.000000z"
- android:fillColor="#FF000000"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_outline.xml b/packages/SystemUI/res/drawable/tv_pip_outline.xml
deleted file mode 100644
index c84438c..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_outline.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <stroke android:width="2dp" android:color="#EEEEEE" />
-</shape>
diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml
deleted file mode 100644
index 996ac5e..0000000
--- a/packages/SystemUI/res/drawable/volume_dialog_background.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<!--
- Copyright (C) 2015 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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="?android:attr/colorBackgroundFloating" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 874cdcc..6864ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -48,14 +48,14 @@
import com.android.settingslib.Utils;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.IconLogger;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 30c92daf..2605a11 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -38,6 +38,7 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.power.EnhancedEstimates;
@@ -45,7 +46,7 @@
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.AmbientPulseManager;
-import com.android.systemui.statusbar.DisplayNavigationBarController;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -79,7 +80,6 @@
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
@@ -244,7 +244,7 @@
@Inject Lazy<NotificationRemoteInputManager.Callback> mNotificationRemoteInputManagerCallback;
@Inject Lazy<InitController> mInitController;
@Inject Lazy<AppOpsController> mAppOpsController;
- @Inject Lazy<DisplayNavigationBarController> mDisplayNavigationBarController;
+ @Inject Lazy<NavigationBarController> mNavigationBarController;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationLockscreenUserManager> mNotificationLockscreenUserManager;
@Inject Lazy<NotificationGroupAlertTransferHelper> mNotificationGroupAlertTransferHelper;
@@ -410,8 +410,7 @@
mProviders.put(AppOpsController.class, mAppOpsController::get);
- mProviders.put(DisplayNavigationBarController.class,
- mDisplayNavigationBarController::get);
+ mProviders.put(NavigationBarController.class, mNavigationBarController::get);
mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
mProviders.put(NotificationLockscreenUserManager.class,
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
index b93a5fd..1ee1dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -19,6 +19,7 @@
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.appops.AppOpsControllerImpl;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
@@ -37,7 +38,6 @@
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.ExtensionController;
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index 2b521c5..5c9b999 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -41,6 +41,7 @@
import com.android.systemui.plugins.PluginInitializerImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -170,6 +171,13 @@
@Singleton
@Provides
+ public NavigationBarController provideNavigationBarController(Context context,
+ @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+ return new NavigationBarController(context, mainHandler);
+ }
+
+ @Singleton
+ @Provides
public ConfigurationController provideConfigurationController(Context context) {
return new ConfigurationControllerImpl(context);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
index 47b56d0..fa5a114 100644
--- a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
+++ b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
@@ -22,22 +22,22 @@
public interface DockManager {
/**
- * Uninitialized / unknown dock states
+ * Uninitialized / undocking dock states
*/
int STATE_NONE = 0;
/**
* The state for docking
*/
- int STATE_DOCKING = 1;
+ int STATE_DOCKED = 1;
/**
- * The state for undocking
+ * The state for docking without showing UI
*/
- int STATE_UNDOCKING = 2;
+ int STATE_DOCKED_HIDE = 2;
/**
* Add a dock event listener into manager
*
- * @param callback A {@link DockEventListener} which want to add
+ * @param callback A {@link DockEventListener} which want to add
*/
void addListener(DockEventListener callback);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 8cd42c7..9fc2234 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -18,11 +18,13 @@
import android.content.Context;
import android.os.Handler;
+import android.os.UserHandle;
import android.util.Log;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.doze.DozeMachine.State;
import java.io.PrintWriter;
@@ -34,7 +36,6 @@
private static final String TAG = "DozeDockHandler";
private static final boolean DEBUG = DozeService.DEBUG;
- private final Context mContext;
private final DozeMachine mMachine;
private final DozeHost mDozeHost;
private final AmbientDisplayConfiguration mConfig;
@@ -42,11 +43,10 @@
private final DockEventListener mDockEventListener = new DockEventListener();
private final DockManager mDockManager;
- private boolean mDocking;
+ private int mDockState = DockManager.STATE_NONE;
public DozeDockHandler(Context context, DozeMachine machine, DozeHost dozeHost,
AmbientDisplayConfiguration config, Handler handler) {
- mContext = context;
mMachine = machine;
mDozeHost = dozeHost;
mConfig = config;
@@ -60,34 +60,35 @@
case INITIALIZED:
mDockEventListener.register();
break;
- case DOZE:
case DOZE_AOD:
- mHandler.post(() -> requestPulse());
+ if (mDockState == DockManager.STATE_DOCKED_HIDE) {
+ mMachine.requestState(State.DOZE);
+ break;
+ }
+ // continue below
+ case DOZE:
+ if (mDockState == DockManager.STATE_DOCKED) {
+ mHandler.post(() -> requestPulse(newState));
+ }
break;
case FINISH:
mDockEventListener.unregister();
break;
default:
+ // no-op
}
}
- private void requestPulse() {
- if (!mDocking || mDozeHost.isPulsingBlocked() || !canPulse()) {
+ private void requestPulse(State dozeState) {
+ if (mDozeHost.isPulsingBlocked() || !dozeState.canPulse()) {
return;
}
mMachine.requestPulse(DozeLog.PULSE_REASON_DOCKING);
}
- private boolean canPulse() {
- return mMachine.getState() == DozeMachine.State.DOZE
- || mMachine.getState() == DozeMachine.State.DOZE_AOD;
- }
-
- private void requestPulseOutNow() {
- final DozeMachine.State state = mMachine.getState();
- if (state == DozeMachine.State.DOZE_PULSING
- || state == DozeMachine.State.DOZE_REQUEST_PULSE) {
+ private void requestPulseOutNow(State dozeState) {
+ if (dozeState == State.DOZE_REQUEST_PULSE || dozeState == State.DOZE_PULSING) {
final int pulseReason = mMachine.getPulseReason();
if (pulseReason == DozeLog.PULSE_REASON_DOCKING) {
mDozeHost.stopPulsing();
@@ -95,9 +96,14 @@
}
}
+ private boolean isDocked() {
+ return mDockState == DockManager.STATE_DOCKED
+ || mDockState == DockManager.STATE_DOCKED_HIDE;
+ }
+
@Override
public void dump(PrintWriter pw) {
- pw.print(" DozeDockTriggers docking="); pw.println(mDocking);
+ pw.print(" DozeDockTriggers docking="); pw.println(isDocked());
}
private class DockEventListener implements DockManager.DockEventListener {
@@ -106,14 +112,21 @@
@Override
public void onEvent(int event) {
if (DEBUG) Log.d(TAG, "dock event = " + event);
- switch (event) {
- case DockManager.STATE_DOCKING:
- mDocking = true;
- requestPulse();
+ final DozeMachine.State dozeState = mMachine.getState();
+ mDockState = event;
+ switch (mDockState) {
+ case DockManager.STATE_DOCKED:
+ requestPulse(dozeState);
break;
- case DockManager.STATE_UNDOCKING:
- mDocking = false;
- requestPulseOutNow();
+ case DockManager.STATE_NONE:
+ if (dozeState == State.DOZE
+ && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
+ mMachine.requestState(State.DOZE_AOD);
+ break;
+ }
+ // continue below
+ case DockManager.STATE_DOCKED_HIDE:
+ requestPulseOutNow(dozeState);
break;
default:
// no-op
@@ -124,7 +137,6 @@
if (mRegistered) {
return;
}
-
if (mDockManager != null) {
mDockManager.addListener(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 35b64ed..b6fc355 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -85,6 +85,7 @@
mProxCallback = proxCallback;
mResolver = mContext.getContentResolver();
+ boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
mSensors = new TriggerSensor[] {
new TriggerSensor(
mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
@@ -116,7 +117,7 @@
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
- mConfig.wakeScreenGestureAvailable(),
+ mConfig.wakeScreenGestureAvailable() && alwaysOn,
DozeLog.REASON_SENSOR_WAKE_UP,
false /* reports touch coordinates */,
false /* touchscreen */),
@@ -359,7 +360,9 @@
}
protected boolean enabledBySetting() {
- if (TextUtils.isEmpty(mSetting)) {
+ if (!mConfig.enabled(UserHandle.USER_CURRENT)) {
+ return false;
+ } else if (TextUtils.isEmpty(mSetting)) {
return true;
}
return Settings.Secure.getIntForUser(mResolver, mSetting, mSettingDefault ? 1 : 0,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index d7d3981..7c937a9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -17,6 +17,7 @@
import android.app.ActivityManager;
import android.app.AlertDialog;
+import android.app.admin.DevicePolicyEventLogger;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -30,6 +31,7 @@
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.Log;
+import android.util.StatsLog;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
@@ -119,6 +121,9 @@
private void handleClick() {
showDeviceMonitoringDialog();
+ DevicePolicyEventLogger
+ .createEvent(StatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED)
+ .write();
}
public void showDeviceMonitoringDialog() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index bec027f..7224599 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -63,6 +63,8 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.privacy.OngoingPrivacyDialog;
import com.android.systemui.privacy.PrivacyItem;
@@ -75,8 +77,6 @@
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.Clock;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
deleted file mode 100644
index 78172f1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.systemui.statusbar;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
-
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.View;
-import android.view.WindowManagerGlobal;
-
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-/**
- * A controller to handle external navigation bars
- */
-@Singleton
-public class DisplayNavigationBarController implements DisplayListener {
-
- private static final String TAG = DisplayNavigationBarController.class.getName();
-
- private final Context mContext;
- private final Handler mHandler;
- private final DisplayManager mDisplayManager;
-
- /** A displayId - nav bar mapping */
- private SparseArray<NavigationBarFragment> mExternalNavigationBarMap = new SparseArray<>();
-
- @Inject
- public DisplayNavigationBarController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler handler) {
- mContext = context;
- mHandler = handler;
- mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
-
- registerListener();
- }
-
- @Override
- public void onDisplayAdded(int displayId) {
- final Display display = mDisplayManager.getDisplay(displayId);
- addExternalNavigationBar(display);
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- final NavigationBarFragment navBar = mExternalNavigationBarMap.get(displayId);
- if (navBar != null) {
- final View navigationView = navBar.getView().getRootView();
- WindowManagerGlobal.getInstance().removeView(navigationView, true);
- mExternalNavigationBarMap.remove(displayId);
- }
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- }
-
- /** Create external navigation bars when car/status bar initializes */
- public void createNavigationBars() {
- // Add external navigation bars if more than one displays exist.
- final Display[] displays = mDisplayManager.getDisplays();
- for (Display display : displays) {
- addExternalNavigationBar(display);
- }
- }
-
- /** remove external navigation bars and unset everything related to external navigation bars */
- public void destroy() {
- unregisterListener();
- if (mExternalNavigationBarMap.size() > 0) {
- for (int i = 0; i < mExternalNavigationBarMap.size(); i++) {
- final View navigationWindow = mExternalNavigationBarMap.valueAt(i)
- .getView().getRootView();
- WindowManagerGlobal.getInstance()
- .removeView(navigationWindow, true /* immediate */);
- }
- mExternalNavigationBarMap.clear();
- }
- }
-
- private void registerListener() {
- mDisplayManager.registerDisplayListener(this, mHandler);
- }
-
- private void unregisterListener() {
- mDisplayManager.unregisterDisplayListener(this);
- }
-
- /**
- * Add a phone navigation bar on an external display if the display supports system decorations.
- *
- * @param display the display to add navigation bar on
- */
- private void addExternalNavigationBar(Display display) {
- if (display == null || display.getDisplayId() == DEFAULT_DISPLAY
- || !display.supportsSystemDecorations()) {
- return;
- }
-
- final int displayId = display.getDisplayId();
- final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
-
- try {
- if (!wms.hasNavigationBar(displayId)) {
- return;
- }
- } catch (RemoteException e) {
- // Cannot get wms, just return with warning message.
- Log.w(TAG, "Cannot get WindowManager.");
- return;
- }
- final Context externalDisplayContext = mContext.createDisplayContext(display);
- NavigationBarFragment.create(externalDisplayContext, (tag, fragment) -> {
- final NavigationBarFragment navBar = (NavigationBarFragment) fragment;
- // TODO(b/115978725): handle external nav bars sysuiVisibility
- navBar.setCurrentSysuiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
- mExternalNavigationBarMap.append(displayId, navBar);
- });
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index b39a96d..e217777 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -31,8 +31,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
new file mode 100644
index 0000000..43eaff4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -0,0 +1,222 @@
+/*
+ * 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.systemui.statusbar;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.View;
+import android.view.WindowManagerGlobal;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.statusbar.policy.BatteryController;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+
+/** A controller to handle navigation bars. */
+@Singleton
+public class NavigationBarController implements DisplayListener {
+
+ private static final String TAG = NavigationBarController.class.getName();
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final DisplayManager mDisplayManager;
+
+ /** A displayId - nav bar maps. */
+ private SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
+
+ @Inject
+ public NavigationBarController(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplayManager.registerDisplayListener(this, mHandler);
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ Display display = mDisplayManager.getDisplay(displayId);
+ createNavigationBar(display);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ removeNavigationBar(displayId);
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ }
+
+ // TODO(b/117478341): I use {@code includeDefaultDisplay} to make this method compatible to
+ // CarStatusBar because they have their own nav bar. Think about a better way for it.
+ /**
+ * Creates navigation bars when car/status bar initializes.
+ *
+ * @param includeDefaultDisplay {@code true} to create navigation bar on default display.
+ */
+ public void createNavigationBars(final boolean includeDefaultDisplay) {
+ Display[] displays = mDisplayManager.getDisplays();
+ for (Display display : displays) {
+ if (includeDefaultDisplay || display.getDisplayId() != DEFAULT_DISPLAY) {
+ createNavigationBar(display);
+ }
+ }
+ }
+
+ /**
+ * Adds a navigation bar on default display or an external display if the display supports
+ * system decorations.
+ *
+ * @param display the display to add navigation bar on.
+ */
+ private void createNavigationBar(Display display) {
+ if (display == null
+ || (display.getDisplayId() != DEFAULT_DISPLAY
+ && !display.supportsSystemDecorations())) {
+ return;
+ }
+
+ final int displayId = display.getDisplayId();
+ final boolean isOnDefaultDisplay = displayId == DEFAULT_DISPLAY;
+ final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
+
+ try {
+ if (!wms.hasNavigationBar(displayId)) {
+ return;
+ }
+ } catch (RemoteException e) {
+ // Cannot get wms, just return with warning message.
+ Log.w(TAG, "Cannot get WindowManager.");
+ return;
+ }
+ final Context context = isOnDefaultDisplay
+ ? mContext
+ : mContext.createDisplayContext(display);
+ NavigationBarFragment.create(context, (tag, fragment) -> {
+ NavigationBarFragment navBar = (NavigationBarFragment) fragment;
+
+ // Unfortunately, we still need it because status bar needs LightBarController
+ // before notifications creation. We cannot directly use getLightBarController()
+ // from NavigationBarFragment directly.
+ LightBarController controller = isOnDefaultDisplay
+ ? Dependency.get(LightBarController.class)
+ : new LightBarController(context,
+ Dependency.get(DarkIconDispatcher.class),
+ Dependency.get(BatteryController.class));
+ navBar.setLightBarController(controller);
+ navBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+ mNavigationBars.append(displayId, navBar);
+ });
+ }
+
+ /** Removes navigation bars. */
+ public void destroy() {
+ mDisplayManager.unregisterDisplayListener(this);
+ if (mNavigationBars.size() > 0) {
+ for (int i = 0; i < mNavigationBars.size(); i++) {
+ int displayId = mNavigationBars.keyAt(i);
+ removeNavigationBar(displayId);
+ }
+ mNavigationBars.clear();
+ }
+ }
+
+ private void removeNavigationBar(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ View navigationWindow = navBar.getView().getRootView();
+ WindowManagerGlobal.getInstance()
+ .removeView(navigationWindow, true /* immediate */);
+ mNavigationBars.remove(displayId);
+ }
+ }
+
+ /** @see NavigationBarFragment#checkNavBarModes() */
+ public void checkNavBarModes(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ navBar.checkNavBarModes();
+ }
+ }
+
+ /** @see NavigationBarFragment#finishBarAnimations() */
+ public void finishBarAnimations(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ navBar.finishBarAnimations();
+ }
+ }
+
+ /** @see NavigationBarFragment#touchAutoDim() */
+ public void touchAutoDim(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ navBar.touchAutoDim();
+ }
+ }
+
+ /** @see NavigationBarFragment#transitionTo(int, boolean) */
+ public void transitionTo(int displayId, @TransitionMode int barMode, boolean animate) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ navBar.transitionTo(barMode, animate);
+ }
+ }
+
+ /** @see NavigationBarFragment#isSemiTransparent() */
+ public boolean isSemiTransparent(int displayId) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ return navBar.isSemiTransparent();
+ }
+ return false;
+ }
+
+ /** @see NavigationBarFragment#disableAnimationsDuringHide(long) */
+ public void disableAnimationsDuringHide(int displayId, long delay) {
+ NavigationBarFragment navBar = mNavigationBars.get(displayId);
+ if (navBar != null) {
+ navBar.disableAnimationsDuringHide(delay);
+ }
+ }
+
+ /** @return {@link NavigationBarView} on the default display. */
+ public NavigationBarView getDefaultNavigationBarView() {
+ NavigationBarFragment navBar = mNavigationBars.get(DEFAULT_DISPLAY);
+ return (navBar == null) ? null : (NavigationBarView) navBar.getView();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 25837e1..1bf101c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -157,7 +157,7 @@
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onEntryRemoved(
- Entry entry,
+ @Nullable Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 674e262..886d99e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -20,6 +20,7 @@
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
@@ -252,13 +253,13 @@
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onEntryRemoved(
- NotificationData.Entry entry,
+ @Nullable NotificationData.Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
boolean lifetimeExtended,
boolean removedByUser) {
- if (removedByUser) {
+ if (removedByUser && entry != null) {
onPerformRemoveNotification(entry, key);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
index f1a891b..d1b3c3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
@@ -30,8 +30,8 @@
import com.android.settingslib.WirelessUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index e7b768f..6d2c001 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -41,9 +41,9 @@
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.IconLogger;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 8b61a5b..3c13354 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
+import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index bc89889..4db981d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -16,11 +16,11 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
+import static com.android.systemui.plugins.DarkIconDispatcher.isInArea;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.isInArea;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -37,8 +37,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
StatusIconDisplayable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index 045221f..c5751c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -16,11 +16,11 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
+import static com.android.systemui.plugins.DarkIconDispatcher.isInArea;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.isInArea;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -37,8 +37,8 @@
import com.android.settingslib.Utils;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
/**
* Start small: StatusBarWifiView will be able to layout from a WifiIconState
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
index beb90b8..d541fae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
public interface StatusIconDisplayable extends DarkReceiver {
String getSlot();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index dbc6f43..7b42dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -20,6 +20,7 @@
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import android.annotation.Nullable;
import android.app.Notification;
import android.service.notification.StatusBarNotification;
import android.util.Log;
@@ -82,7 +83,7 @@
@Override
public void onEntryRemoved(
- NotificationData.Entry entry,
+ @Nullable NotificationData.Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 27c2837..a51896e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -90,7 +90,7 @@
private static final long INITIALIZATION_DELAY = 400;
private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
private static final int COLOR_INVALID = 1;
- public String key;
+ public final String key;
public StatusBarNotification notification;
public NotificationChannel channel;
public long lastAudiblyAlertedMs;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 72f1d5b..1d06ce0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -80,7 +80,7 @@
* @param removedByUser true if the notification was removed by a user action
*/
default void onEntryRemoved(
- NotificationData.Entry entry,
+ @Nullable NotificationData.Entry entry,
String key,
StatusBarNotification old,
@Nullable NotificationVisibility visibility,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 060e755..610d300 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.statusbar.notification.logging;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
@@ -167,13 +168,13 @@
entryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onEntryRemoved(
- NotificationData.Entry entry,
+ @Nullable NotificationData.Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
boolean lifetimeExtended,
boolean removedByUser) {
- if (removedByUser && visibility != null) {
+ if (removedByUser && visibility != null && entry != null) {
logNotificationClear(key, entry.notification, visibility);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 5329541..b1eab80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -40,6 +40,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
@@ -150,6 +151,7 @@
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
+ mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
swapContent(ACTION_UNDO, true /* animate */);
};
@@ -381,6 +383,17 @@
}
}
+ /**
+ * Returns an initialized LogMaker for logging importance changes.
+ * The caller may override the type (to DISMISS) before passing it to mMetricsLogger.
+ * @return new LogMaker
+ */
+ private LogMaker importanceChangeLogMaker() {
+ return new LogMaker(MetricsEvent.ACTION_SAVE_IMPORTANCE)
+ .setType(MetricsEvent.TYPE_ACTION)
+ .setSubtype(mChosenImportance - mStartingChannelImportance);
+ }
+
private boolean hasImportanceChanged() {
return mSingleNotificationChannel != null
&& mStartingChannelImportance != mChosenImportance;
@@ -397,8 +410,7 @@
* Commits the updated importance values on the background thread.
*/
private void updateImportance() {
- MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
- mChosenImportance - mStartingChannelImportance);
+ mMetricsLogger.write(importanceChangeLogMaker());
Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
index 8c8bad2..a5411ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageCache.java
@@ -87,8 +87,8 @@
try {
drawable = mResolver.resolveImage(target);
- } catch (IOException ex) {
- Log.d(TAG, "PreloadImageTask: Resolve failed from " + target);
+ } catch (IOException | SecurityException ex) {
+ Log.d(TAG, "PreloadImageTask: Resolve failed from " + target, ex);
}
return drawable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
index 588246f..a3e1305 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
@@ -81,8 +81,8 @@
Drawable result = null;
try {
result = hasCache() ? mImageCache.get(uri) : resolveImage(uri);
- } catch (IOException ex) {
- Log.d(TAG, "loadImage: Can't load image from " + uri);
+ } catch (IOException | SecurityException ex) {
+ Log.d(TAG, "loadImage: Can't load image from " + uri, ex);
}
return result;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 3d81473..7905617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.annotation.IntDef;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -36,6 +37,9 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class BarTransitions {
private static final boolean DEBUG = false;
private static final boolean DEBUG_COLORS = false;
@@ -48,6 +52,18 @@
public static final int MODE_WARNING = 5;
public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
+ @IntDef(flag = true, prefix = { "MODE_" }, value = {
+ MODE_OPAQUE,
+ MODE_SEMI_TRANSPARENT,
+ MODE_TRANSLUCENT,
+ MODE_LIGHTS_OUT,
+ MODE_TRANSPARENT,
+ MODE_WARNING,
+ MODE_LIGHTS_OUT_TRANSPARENT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TransitionMode {}
+
public static final int LIGHTS_IN_DURATION = 250;
public static final int LIGHTS_OUT_DURATION = 1500;
public static final int BACKGROUND_DURATION = 200;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
index 5b44a77..08a10dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -14,7 +14,8 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
+import static com.android.systemui.plugins.DarkIconDispatcher.DEFAULT_ICON_TINT;
+import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
import android.animation.ArgbEvaluator;
import android.content.Context;
@@ -24,7 +25,7 @@
import android.widget.ImageView;
import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -35,7 +36,7 @@
/**
*/
@Singleton
-public class DarkIconDispatcherImpl implements DarkIconDispatcher {
+public class DarkIconDispatcherImpl implements SysuiDarkIconDispatcher {
private final LightBarTransitionsController mTransitionsController;
private final Rect mTintArea = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 3425dd2..236c72c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -29,14 +29,14 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 3c8cad7..d1e488a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -25,12 +25,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import java.util.function.BiConsumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 5ba59b5..03375d20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -45,13 +45,13 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 6632d58..b590ca7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -27,8 +27,8 @@
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,7 +44,7 @@
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
- private final DarkIconDispatcher mStatusBarIconController;
+ private final SysuiDarkIconDispatcher mStatusBarIconController;
private final BatteryController mBatteryController;
private BiometricUnlockController mBiometricUnlockController;
@@ -79,16 +79,13 @@
private final Rect mLastDockedBounds = new Rect();
private boolean mQsCustomizing;
- private final Context mContext;
-
@Inject
public LightBarController(Context ctx, DarkIconDispatcher darkIconDispatcher,
BatteryController batteryController) {
mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
- mStatusBarIconController = darkIconDispatcher;
+ mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
mBatteryController = batteryController;
mBatteryController.addCallback(this);
- mContext = ctx;
}
public void setNavigationBar(LightBarTransitionsController navigationBar) {
@@ -225,9 +222,8 @@
private void updateNavigation() {
if (mNavigationBarController != null) {
- if (!NavBarTintController.isEnabled(mContext)) {
- mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
- }
+ mNavigationBarController.setIconsDark(
+ mNavigationLight, animateChange());
}
}
@@ -268,10 +264,6 @@
pw.println();
- if (mStatusBarIconController != null) {
- mStatusBarIconController.dump(fd, pw, args);
- }
-
LightBarTransitionsController transitionsController =
mStatusBarIconController.getTransitionsController();
if (transitionsController != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 2daff2c..270565b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -16,14 +16,19 @@
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
@@ -55,6 +60,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
+import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -63,6 +69,7 @@
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
@@ -72,6 +79,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
@@ -83,6 +91,8 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.ContextualButton.ContextButtonListener;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
@@ -111,6 +121,7 @@
/** Allow some time inbetween the long press for back and recents. */
private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
+ private static final long AUTOHIDE_TIMEOUT_MS = 2250;
private final AccessibilityManagerWrapper mAccessibilityManagerWrapper;
protected final AssistManager mAssistManager;
@@ -122,10 +133,11 @@
private int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
private int mNavigationIconHints = 0;
- private int mNavigationBarMode;
+ private @TransitionMode int mNavigationBarMode;
private AccessibilityManager mAccessibilityManager;
private MagnificationContentObserver mMagnificationObserver;
private ContentResolver mContentResolver;
+ private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
private int mDisabledFlags1;
private int mDisabledFlags2;
@@ -144,9 +156,15 @@
private OverviewProxyService mOverviewProxyService;
- private boolean mIsOnDefaultDisplay = true;
+ private int mDisplayId;
+ private boolean mIsOnDefaultDisplay;
public boolean mHomeBlockedThisTouch;
+ private Handler mHandler = Dependency.get(Dependency.MAIN_HANDLER);
+
+ // last value sent to window manager
+ private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
+
private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@Override
public void onConnectionChanged(boolean isConnected) {
@@ -183,14 +201,20 @@
}
};
- private final ContextButtonListener mRotationButtonListener = new ContextButtonListener() {
- @Override
- public void onVisibilityChanged(ContextualButton button, boolean visible) {
- if (visible) {
- // If the button will actually become visible and the navbar is about to hide,
- // tell the statusbar to keep it around for longer
- mStatusBar.touchAutoHide();
- }
+ private final ContextButtonListener mRotationButtonListener = (button, visible) -> {
+ if (visible) {
+ // If the button will actually become visible and the navbar is about to hide,
+ // tell the statusbar to keep it around for longer
+ touchAutoHide();
+ }
+ };
+
+ private final Runnable mAutoDim = () -> getBarTransitions().setAutoDim(true);
+
+ private final Runnable mAutoHide = () -> {
+ int requested = mSystemUiVisibility & ~View.NAVIGATION_BAR_TRANSIENT;
+ if (mSystemUiVisibility != requested) {
+ notifySystemUiVisibilityChanged(requested);
}
};
@@ -251,7 +275,8 @@
final Display display = view.getDisplay();
// It may not have display when running unit test.
if (display != null) {
- mIsOnDefaultDisplay = display.getDisplayId() == Display.DEFAULT_DISPLAY;
+ mDisplayId = display.getDisplayId();
+ mIsOnDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
}
mNavigationBarView.setComponents(mStatusBar.getPanel());
@@ -381,7 +406,7 @@
if (mNavigationBarView != null) {
mNavigationBarView.setNavigationIconHints(hints);
}
- mStatusBar.checkBarModes();
+ checkBarModes();
}
@Override
@@ -426,23 +451,22 @@
.onRotationProposal(rotation, winRotation, isValid);
}
- // Injected from StatusBar at creation.
- public void setCurrentSysuiVisibility(int systemUiVisibility) {
+ /**
+ * Sets System UI flags to {@link NavigationBarFragment}.
+ *
+ * @see View#setSystemUiVisibility(int)
+ */
+ public void setSystemUiVisibility(int systemUiVisibility) {
mSystemUiVisibility = systemUiVisibility;
- final int barMode = mStatusBar.computeBarMode(0, mSystemUiVisibility,
- View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
- View.NAVIGATION_BAR_TRANSPARENT);
+ final int barMode = computeBarMode(0, mSystemUiVisibility);
if (barMode != -1) {
mNavigationBarMode = barMode;
}
checkNavBarModes();
- mStatusBar.touchAutoHide();
+ touchAutoHide();
- // TODO(115978725): Support light bar controller on external nav bars.
- if (mLightBarController != null) {
- mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
+ mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
true /* nbModeChanged */, mNavigationBarMode);
- }
}
@Override
@@ -457,9 +481,7 @@
// update navigation bar mode
final int nbMode = getView() == null
- ? -1 : mStatusBar.computeBarMode(oldVal, newVal,
- View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
- View.NAVIGATION_BAR_TRANSPARENT);
+ ? -1 : computeBarMode(oldVal, newVal);
nbModeChanged = nbMode != -1;
if (nbModeChanged) {
if (mNavigationBarMode != nbMode) {
@@ -470,14 +492,46 @@
mNavigationBarMode = nbMode;
checkNavBarModes();
}
- mStatusBar.touchAutoHide();
+ touchAutoHide();
+ }
+ if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
+ mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
+ }
+
+
+ // On the default display, just make StatusBar do this job.
+ if (!mIsOnDefaultDisplay) {
+ notifySystemUiVisibilityChanged(mSystemUiVisibility);
}
}
+ mLightBarController.onNavigationVisibilityChanged(
+ vis, mask, nbModeChanged, mNavigationBarMode);
+ }
- // TODO(115978725): Support light bar controller on external nav bars.
- if (mLightBarController != null) {
- mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
- mNavigationBarMode);
+ private @TransitionMode int computeBarMode(int oldVis, int newVis) {
+ final int oldMode = barMode(oldVis);
+ final int newMode = barMode(newVis);
+ if (oldMode == newMode) {
+ return -1; // no mode change
+ }
+ return newMode;
+ }
+
+ private @TransitionMode int barMode(int vis) {
+ final int lightsOutTransparent =
+ View.SYSTEM_UI_FLAG_LOW_PROFILE | View.NAVIGATION_BAR_TRANSIENT;
+ if ((vis & View.NAVIGATION_BAR_TRANSIENT) != 0) {
+ return MODE_SEMI_TRANSPARENT;
+ } else if ((vis & View.NAVIGATION_BAR_TRANSLUCENT) != 0) {
+ return MODE_TRANSLUCENT;
+ } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((vis & View.NAVIGATION_BAR_TRANSPARENT) != 0) {
+ return MODE_TRANSPARENT;
+ } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ return MODE_LIGHTS_OUT;
+ } else {
+ return MODE_OPAQUE;
}
}
@@ -511,7 +565,7 @@
}
}
- // ----- Internal stuffz -----
+ // ----- Internal stuff -----
private void refreshLayout(int layoutDirection) {
if (mNavigationBarView != null) {
@@ -610,7 +664,7 @@
}
private boolean onNavigationTouch(View v, MotionEvent event) {
- mStatusBar.checkUserAutohide(event);
+ checkUserAutoHide(event);
return false;
}
@@ -800,7 +854,79 @@
mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection);
}
- // ----- Methods that StatusBar talks to (should be minimized) -----
+ private void touchAutoHide() {
+ // There is status bar on default display. Thus the hide animations should apply on both
+ // status/navigation bar.
+ if (mIsOnDefaultDisplay) {
+ mStatusBar.touchAutoHide();
+ } else {
+ touchAutoHideInternal();
+ }
+ }
+
+ private void touchAutoHideInternal() {
+ // update transient bar autoHide.
+ if (isSemiTransparent()) {
+ scheduleAutoHide();
+ } else {
+ cancelAutoHide();
+ }
+ }
+
+ private void checkUserAutoHide(MotionEvent event) {
+ // There is status bar on default display. Thus the hide animations should apply on both
+ // status/navigation bar.
+ if (mIsOnDefaultDisplay) {
+ mStatusBar.checkUserAutoHide(event);
+ } else {
+ checkUserAutoHideInternal(event);
+ }
+ }
+
+ private void checkUserAutoHideInternal(MotionEvent event) {
+ if ((mSystemUiVisibility & View.NAVIGATION_BAR_TRANSIENT) != 0
+ // a transient bar is revealed
+ && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
+ && event.getX() == 0 && event.getY() == 0) { // a touch outside both bars.
+ userAutoHide();
+ }
+ }
+
+ private void userAutoHide() {
+ cancelAutoHide();
+ mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear.
+ }
+
+ private void cancelAutoHide() {
+ mHandler.removeCallbacks(mAutoHide);
+ }
+
+ private void scheduleAutoHide() {
+ cancelAutoHide();
+ mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
+ }
+
+ private void notifySystemUiVisibilityChanged(int vis) {
+ try {
+ if (mLastDispatchedSystemUiVisibility != vis) {
+ mWindowManagerService.statusBarVisibilityChanged(mDisplayId, vis);
+ mLastDispatchedSystemUiVisibility = vis;
+ }
+ } catch (RemoteException ex) {
+ }
+ }
+
+ // ----- Methods that DisplayNavigationBarController talks to -----
+
+ /** Applys auto dimming animation on navigation bar when touched. */
+ public void touchAutoDim() {
+ getBarTransitions().setAutoDim(false);
+ mHandler.removeCallbacks(mAutoDim);
+ int state = Dependency.get(StatusBarStateController.class).getState();
+ if (state != StatusBarState.KEYGUARD && state != StatusBarState.SHADE_LOCKED) {
+ mHandler.postDelayed(mAutoDim, AUTOHIDE_TIMEOUT_MS);
+ }
+ }
public void setLightBarController(LightBarController lightBarController) {
mLightBarController = lightBarController;
@@ -811,19 +937,42 @@
return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
}
+ private void checkBarModes() {
+ // We only have status bar on default display now.
+ if (mIsOnDefaultDisplay) {
+ mStatusBar.checkBarModes();
+ } else {
+ checkNavBarModes();
+ }
+ }
+
+ /**
+ * Checks current navigation bar mode and make transitions.
+ */
+ public void checkNavBarModes() {
+ final boolean anim = mStatusBar.isDeviceInteractive()
+ && mNavigationBarWindowState != WINDOW_STATE_HIDDEN;
+ mNavigationBarView.getBarTransitions().transitionTo(mNavigationBarMode, anim);
+ }
+
public void disableAnimationsDuringHide(long delay) {
mNavigationBarView.setLayoutTransitionsEnabled(false);
mNavigationBarView.postDelayed(() -> mNavigationBarView.setLayoutTransitionsEnabled(true),
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
}
- public BarTransitions getBarTransitions() {
- return mNavigationBarView.getBarTransitions();
+ /**
+ * Performs transitions on navigation bar.
+ *
+ * @param barMode transition bar mode.
+ * @param animate shows animations if {@code true}.
+ */
+ public void transitionTo(@TransitionMode int barMode, boolean animate) {
+ getBarTransitions().transitionTo(barMode, animate);
}
- public void checkNavBarModes() {
- mStatusBar.checkBarMode(mNavigationBarMode,
- mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
+ private BarTransitions getBarTransitions() {
+ return mNavigationBarView.getBarTransitions();
}
public void finishBarAnimations() {
@@ -873,12 +1022,11 @@
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
// The accessibility settings may be different for the new user
updateAccessibilityServicesState(mAccessibilityManager);
- };
+ }
}
};
public static View create(Context context, FragmentListener listener) {
- final int displayId = context.getDisplay().getDisplayId();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
@@ -890,7 +1038,7 @@
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
lp.token = new Binder();
- lp.setTitle("NavigationBar" + displayId);
+ lp.setTitle("NavigationBar" + context.getDisplayId());
lp.accessibilityTitle = context.getString(R.string.nav_bar);
lp.windowAnimations = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 8c17922..2fc7b78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -282,6 +282,11 @@
}
@Override
+ public void onHomeButtonVisibilityChanged(boolean visible) {
+ getHomeButton().setVisibility(visible ? VISIBLE : GONE);
+ }
+
+ @Override
public void onColorAdaptChanged(boolean enabled) {
if (enabled) {
mColorAdaptionController.start();
@@ -672,6 +677,7 @@
// TODO(b/113914868): investigation log for disappearing home button
Log.i(TAG, "updateNavButtonIcons (b/113914868): home disabled=" + disableHome
+ " mDisabledFlags=" + mDisabledFlags);
+ disableHome |= mPrototypeController.hideHomeButton();
// Always disable recents when alternate car mode UI is active and for secondary displays.
boolean disableRecent = isRecentsButtonDisabled();
@@ -945,6 +951,7 @@
// TODO(b/112934365): remove after prototype finished, only needed to escape from pin
getBackButton().setVisibility(VISIBLE);
+ getHomeButton().setVisibility(VISIBLE);
} else {
mScreenPinningNotify.showPinningExitToast();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index 40ac793..fb6254b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -34,6 +34,7 @@
*/
public class NavigationPrototypeController extends ContentObserver {
private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback";
+ private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome";
static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
@@ -73,6 +74,7 @@
*/
public void register() {
registerObserver(HIDE_BACK_BUTTON_SETTING);
+ registerObserver(HIDE_HOME_BUTTON_SETTING);
registerObserver(GESTURE_MATCH_SETTING);
registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING);
}
@@ -88,22 +90,20 @@
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (!selfChange && mListener != null) {
- try {
- final String path = uri.getPath();
- if (path.endsWith(GESTURE_MATCH_SETTING)) {
- // Get the settings gesture map corresponding to each action
- // {@see updateSwipeLTRBackSetting}
- updateSwipeLTRBackSetting();
- mListener.onGestureRemap(mActionMap);
- } else if (path.endsWith(HIDE_BACK_BUTTON_SETTING)) {
- mListener.onBackButtonVisibilityChanged(
- !getGlobalBool(HIDE_BACK_BUTTON_SETTING));
- } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
- mListener.onColorAdaptChanged(
- NavBarTintController.isEnabled(mContext));
- }
- } catch (SettingNotFoundException e) {
- e.printStackTrace();
+ final String path = uri.getPath();
+ if (path.endsWith(GESTURE_MATCH_SETTING)) {
+ // Get the settings gesture map corresponding to each action
+ // {@see updateSwipeLTRBackSetting}
+ updateSwipeLTRBackSetting();
+ mListener.onGestureRemap(mActionMap);
+ } else if (path.endsWith(HIDE_BACK_BUTTON_SETTING)) {
+ mListener.onBackButtonVisibilityChanged(
+ !getGlobalBool(HIDE_BACK_BUTTON_SETTING, false));
+ } else if (path.endsWith(HIDE_HOME_BUTTON_SETTING)) {
+ mListener.onHomeButtonVisibilityChanged(!hideHomeButton());
+ } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
+ mListener.onColorAdaptChanged(
+ NavBarTintController.isEnabled(mContext));
}
}
}
@@ -117,6 +117,13 @@
}
/**
+ * @return if home button should be invisible
+ */
+ boolean hideHomeButton() {
+ return getGlobalBool(HIDE_HOME_BUTTON_SETTING, false /* default */);
+ }
+
+ /**
* Since Settings.Global cannot pass arrays, use a string to represent each character as a
* gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
* Number: [up] [down] [left] [right]
@@ -131,8 +138,8 @@
}
}
- private boolean getGlobalBool(String name) throws SettingNotFoundException {
- return Settings.Global.getInt(mContext.getContentResolver(), name) == 1;
+ private boolean getGlobalBool(String name, boolean defaultVal) {
+ return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal ? 1 : 0) == 1;
}
private void registerObserver(String name) {
@@ -143,6 +150,7 @@
public interface OnPrototypeChangedListener {
void onGestureRemap(@GestureAction int[] actions);
void onBackButtonVisibilityChanged(boolean visible);
+ void onHomeButtonVisibilityChanged(boolean visible);
void onColorAdaptChanged(boolean enabled);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
index 9fe30db..3839ed5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupAlertTransferHelper.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Notification;
import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
@@ -218,7 +219,7 @@
@Override
public void onEntryRemoved(
- Entry entry,
+ @Nullable Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index e40835f..056c8a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -19,14 +19,14 @@
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 1b18c6c..fd34ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2803,6 +2803,11 @@
if (animatePulse) {
mAnimateNextPositionUpdate = true;
}
+ // Do not animate the clock when waking up from a pulse.
+ // The height callback will take care of pushing the clock to the right position.
+ if (!mPulsing && !mDozing) {
+ mAnimateNextPositionUpdate = false;
+ }
mNotificationStackScroller.setPulsing(pulsing, animatePulse);
mKeyguardStatusView.setPulsing(pulsing, animatePulse);
mKeyguardBottomArea.setPulsing(pulsing, animatePulse);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 2129835..7a3d03f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -43,9 +43,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import java.util.Objects;
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 e1a6cd3..9f0eec4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -37,6 +37,7 @@
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
+import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -71,7 +72,6 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
import android.media.AudioAttributes;
import android.metrics.LogMaker;
import android.net.Uri;
@@ -155,6 +155,8 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
@@ -168,11 +170,11 @@
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.DisplayNavigationBarController;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -204,7 +206,6 @@
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
@@ -446,18 +447,18 @@
protected final H mHandler = createHandler();
private int mInteractingWindows;
- private boolean mAutohideSuspended;
- private int mStatusBarMode;
+ private boolean mAutoHideSuspended;
+ private @TransitionMode int mStatusBarMode;
private ViewMediatorCallback mKeyguardViewMediatorCallback;
protected ScrimController mScrimController;
protected DozeScrimController mDozeScrimController;
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
- private final Runnable mAutohide = () -> {
+ private final Runnable mAutoHide = () -> {
int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT;
if (mSystemUiVisibility != requested) {
- notifyUiVisibilityChanged(requested);
+ notifySystemUiVisibilityChanged(requested);
}
};
@@ -584,11 +585,6 @@
}
};
- protected DisplayManager mDisplayManager;
-
- private NavigationBarFragment mNavigationBar;
- private View mNavigationBarView;
-
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private boolean mVibrateOnOpening;
private VibratorHelper mVibratorHelper;
@@ -642,7 +638,7 @@
mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
- mNavigationBarController = Dependency.get(DisplayNavigationBarController.class);
+ mNavigationBarController = Dependency.get(NavigationBarController.class);
mBubbleController = Dependency.get(BubbleController.class);
mBubbleController.setExpandListener(mBubbleExpandListener);
KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
@@ -808,6 +804,9 @@
mNotificationIconAreaController.setupShelf(mNotificationShelf);
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
+ // Allow plugins to reference DarkIconDispatcher
+ Dependency.get(PluginDependencyProvider.class)
+ .allowPluginDependency(DarkIconDispatcher.class);
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
@@ -903,11 +902,7 @@
}
});
- // TODO(115978725): Support light bar controller on external nav bars.
mLightBarController = Dependency.get(LightBarController.class);
- if (mNavigationBar != null) {
- mNavigationBar.setLightBarController(mLightBarController);
- }
ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front);
@@ -1093,25 +1088,10 @@
}
}
+ // TODO(b/117478341): This was left such that CarStatusBar can override this method.
+ // Try to remove this.
protected void createNavigationBar() {
- try {
- // TODO(117478341): Move this into DisplayNavigationBarController#createNavigationBars
- // for-loop. We will also move the whole navigation bar logic together.
- final boolean showNav = mWindowManagerService.hasNavigationBar(DEFAULT_DISPLAY);
- if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
- if (!showNav) return;
-
- mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
- mNavigationBar = (NavigationBarFragment) fragment;
- if (mLightBarController != null) {
- mNavigationBar.setLightBarController(mLightBarController);
- }
- mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
- });
- } catch (RemoteException ex) {
- // no window manager? good luck with that
- }
- mNavigationBarController.createNavigationBars();
+ mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */);
}
/**
@@ -1120,7 +1100,7 @@
*/
protected View.OnTouchListener getStatusBarWindowTouchListener() {
return (v, event) -> {
- checkUserAutohide(event);
+ checkUserAutoHide(event);
mRemoteInputManager.checkRemoteInputOutside(event);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mExpandedVisible) {
@@ -2101,7 +2081,7 @@
}
// send updated sysui visibility to window manager
- notifyUiVisibilityChanged(mSystemUiVisibility);
+ notifySystemUiVisibilityChanged(mSystemUiVisibility);
}
mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
@@ -2131,52 +2111,55 @@
}
}
- // TODO(115978725): Support auto hide on external nav bars.
void touchAutoHide() {
- // update transient bar autohide
- if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null
- && mNavigationBar.isSemiTransparent())) {
- scheduleAutohide();
+ // update transient bar auto hide
+ if (mStatusBarMode == MODE_SEMI_TRANSPARENT
+ || mNavigationBarController.isSemiTransparent(DEFAULT_DISPLAY)) {
+ scheduleAutoHide();
} else {
- cancelAutohide();
+ cancelAutoHide();
}
}
- protected int computeStatusBarMode(int oldVal, int newVal) {
- return computeBarMode(oldVal, newVal, View.STATUS_BAR_TRANSIENT,
- View.STATUS_BAR_TRANSLUCENT, View.STATUS_BAR_TRANSPARENT);
+ protected @TransitionMode int computeStatusBarMode(int oldVal, int newVal) {
+ return computeBarMode(oldVal, newVal);
}
protected BarTransitions getStatusBarTransitions() {
return mStatusBarView.getBarTransitions();
}
- protected int computeBarMode(int oldVis, int newVis,
- int transientFlag, int translucentFlag, int transparentFlag) {
- final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag);
- final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag);
+ protected @TransitionMode int computeBarMode(int oldVis, int newVis) {
+ final int oldMode = barMode(oldVis);
+ final int newMode = barMode(newVis);
if (oldMode == newMode) {
return -1; // no mode change
}
return newMode;
}
- private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) {
- int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag;
- return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
- : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
- : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
- : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT
- : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
- : MODE_OPAQUE;
+ private @TransitionMode int barMode(int vis) {
+ int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.STATUS_BAR_TRANSPARENT;
+ if ((vis & View.STATUS_BAR_TRANSIENT) != 0) {
+ return MODE_SEMI_TRANSPARENT;
+ } else if ((vis & View.STATUS_BAR_TRANSLUCENT) != 0) {
+ return MODE_TRANSLUCENT;
+ } else if ((vis & lightsOutTransparent) == lightsOutTransparent) {
+ return MODE_LIGHTS_OUT_TRANSPARENT;
+ } else if ((vis & View.STATUS_BAR_TRANSPARENT) != 0) {
+ return MODE_TRANSPARENT;
+ } else if ((vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
+ return MODE_LIGHTS_OUT;
+ } else {
+ return MODE_OPAQUE;
+ }
}
- // TODO(115978725): Support animations on external nav bars.
void checkBarModes() {
if (mDemoMode) return;
if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
getStatusBarTransitions());
- if (mNavigationBar != null) mNavigationBar.checkNavBarModes();
+ mNavigationBarController.checkNavBarModes(DEFAULT_DISPLAY);
mNoAnimationOnNextBarModeChange = false;
}
@@ -2185,20 +2168,17 @@
mNotificationPanel.setQsScrimEnabled(scrimEnabled);
}
- void checkBarMode(int mode, int windowState, BarTransitions transitions) {
+ void checkBarMode(@TransitionMode int mode, int windowState, BarTransitions transitions) {
final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive
&& windowState != WINDOW_STATE_HIDDEN;
transitions.transitionTo(mode, anim);
}
- // TODO(115978725): Support animations on external nav bars.
private void finishBarAnimations() {
if (mStatusBarView != null) {
mStatusBarView.getBarTransitions().finishAnimations();
}
- if (mNavigationBar != null) {
- mNavigationBar.finishBarAnimations();
- }
+ mNavigationBarController.finishBarAnimations(DEFAULT_DISPLAY);
}
private final Runnable mCheckBarModes = this::checkBarModes;
@@ -2209,13 +2189,13 @@
? (mInteractingWindows | barWindow)
: (mInteractingWindows & ~barWindow);
if (mInteractingWindows != 0) {
- suspendAutohide();
+ suspendAutoHide();
} else {
- resumeSuspendedAutohide();
+ resumeSuspendedAutoHide();
}
// manually dismiss the volume panel when interacting with the nav bar
if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) {
- touchAutoDim();
+ mNavigationBarController.touchAutoDim(DEFAULT_DISPLAY);
dismissVolumeDialog();
}
checkBarModes();
@@ -2227,57 +2207,42 @@
}
}
- private void resumeSuspendedAutohide() {
- if (mAutohideSuspended) {
- scheduleAutohide();
+ private void resumeSuspendedAutoHide() {
+ if (mAutoHideSuspended) {
+ scheduleAutoHide();
mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher
}
}
- private void suspendAutohide() {
- mHandler.removeCallbacks(mAutohide);
+ private void suspendAutoHide() {
+ mHandler.removeCallbacks(mAutoHide);
mHandler.removeCallbacks(mCheckBarModes);
- mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0;
+ mAutoHideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0;
}
- private void cancelAutohide() {
- mAutohideSuspended = false;
- mHandler.removeCallbacks(mAutohide);
+ private void cancelAutoHide() {
+ mAutoHideSuspended = false;
+ mHandler.removeCallbacks(mAutoHide);
}
- private void scheduleAutohide() {
- cancelAutohide();
- mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS);
+ private void scheduleAutoHide() {
+ cancelAutoHide();
+ mHandler.postDelayed(mAutoHide, AUTOHIDE_TIMEOUT_MS);
}
- public void touchAutoDim() {
- if (mNavigationBar != null) {
- mNavigationBar.getBarTransitions().setAutoDim(false);
- }
- mHandler.removeCallbacks(mAutoDim);
-
- // Do not dim the navigation buttons if the its tint is controlled by the bar's background
- if (NavBarTintController.isEnabled(mContext)) {
- return;
- }
- if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
- mHandler.postDelayed(mAutoDim, AUTOHIDE_TIMEOUT_MS);
- }
- }
-
- void checkUserAutohide(MotionEvent event) {
+ void checkUserAutoHide(MotionEvent event) {
if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed
&& event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar
&& event.getX() == 0 && event.getY() == 0 // a touch outside both bars
&& !mRemoteInputManager.getController()
.isRemoteInputActive()) { // not due to typing in IME
- userAutohide();
+ userAutoHide();
}
}
- private void userAutohide() {
- cancelAutohide();
- mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear
+ private void userAutoHide() {
+ cancelAutoHide();
+ mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
}
private boolean areLightsOn() {
@@ -2296,11 +2261,10 @@
}
}
- private void notifyUiVisibilityChanged(int vis) {
+ private void notifySystemUiVisibilityChanged(int vis) {
try {
if (mLastDispatchedSystemUiVisibility != vis) {
- // TODO (b/117478341): Resolve one status bar/ navigation bar assumption
- mWindowManagerService.statusBarVisibilityChanged(Display.DEFAULT_DISPLAY, vis);
+ mWindowManagerService.statusBarVisibilityChanged(DEFAULT_DISPLAY, vis);
mLastDispatchedSystemUiVisibility = vis;
}
} catch (RemoteException ex) {
@@ -2925,10 +2889,6 @@
mWindowManager.removeViewImmediate(mStatusBarWindow);
mStatusBarWindow = null;
}
- if (mNavigationBarView != null) {
- mWindowManager.removeViewImmediate(mNavigationBarView);
- mNavigationBarView = null;
- }
mNavigationBarController.destroy();
mContext.unregisterReceiver(mBroadcastReceiver);
mContext.unregisterReceiver(mDemoReceiver);
@@ -2998,15 +2958,12 @@
"transparent".equals(mode) ? MODE_TRANSPARENT :
"warning".equals(mode) ? MODE_WARNING :
-1;
- // TODO(115978725): Support external nav bar transitions
if (barMode != -1) {
boolean animate = true;
if (mStatusBarView != null) {
mStatusBarView.getBarTransitions().transitionTo(barMode, animate);
}
- if (mNavigationBar != null) {
- mNavigationBar.getBarTransitions().transitionTo(barMode, animate);
- }
+ mNavigationBarController.transitionTo(DEFAULT_DISPLAY, barMode, animate);
}
}
if (modeChange || command.equals(COMMAND_OPERATOR)) {
@@ -3232,12 +3189,9 @@
mDraggedDownEntry = null;
}
- // TODO(115978725): Support animations on external nav bars.
// Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device.
- if (mNavigationBar != null) {
- mNavigationBar.disableAnimationsDuringHide(delay);
- }
+ mNavigationBarController.disableAnimationsDuringHide(DEFAULT_DISPLAY, delay);
} else if (!mNotificationPanel.isCollapsing()) {
instantCollapseNotificationPanel();
}
@@ -3467,7 +3421,7 @@
updateReportRejectedTouchVisibility();
updateDozing();
updateTheme();
- touchAutoDim();
+ mNavigationBarController.touchAutoDim(DEFAULT_DISPLAY);
Trace.beginSection("StatusBar#updateKeyguardState");
if (mState == StatusBarState.KEYGUARD) {
mKeyguardIndicationController.setVisible(true);
@@ -3588,11 +3542,7 @@
// TODO: Figure out way to remove these.
public NavigationBarView getNavigationBarView() {
- return (mNavigationBar != null ? (NavigationBarView) mNavigationBar.getView() : null);
- }
-
- public View getNavigationBarWindow() {
- return mNavigationBarView;
+ return mNavigationBarController.getDefaultNavigationBarView();
}
/**
@@ -4174,7 +4124,7 @@
private DeviceProvisionedController mDeviceProvisionedController
= Dependency.get(DeviceProvisionedController.class);
- protected DisplayNavigationBarController mNavigationBarController;
+ protected NavigationBarController mNavigationBarController;
// UI-specific methods
@@ -4502,13 +4452,6 @@
}
// End Extra BaseStatusBarMethods.
- // TODO(115978725): Handle dimming for external nav bars
- private final Runnable mAutoDim = () -> {
- if (mNavigationBar != null) {
- mNavigationBar.getBarTransitions().setAutoDim(true);
- }
- };
-
public NotificationGutsManager getGutsManager() {
return mGutsManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 26c9d28..2e2ff1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -38,14 +38,14 @@
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.util.Utils.DisableStateTracker;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 7b6fef3..7b7bcb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -20,6 +20,7 @@
import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
+import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -193,7 +194,7 @@
@Override
public void onEntryRemoved(
- Entry entry,
+ @Nullable Entry entry,
String key,
StatusBarNotification old,
NotificationVisibility visibility,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
new file mode 100644
index 0000000..d537721
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
@@ -0,0 +1,32 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.plugins.DarkIconDispatcher;
+
+/**
+ * Dispatches events to {@link DarkReceiver}s about changes in darkness, tint area
+ * and dark intensity.
+ */
+public interface SysuiDarkIconDispatcher extends DarkIconDispatcher, Dumpable {
+
+ /**
+ * @return LightBarTransitionsController
+ */
+ LightBarTransitionsController getTransitionsController();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index aafdcd5..5eb3e89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -44,11 +44,12 @@
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
deleted file mode 100644
index 0823db9..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.view.View;
-import android.widget.ImageView;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.statusbar.phone.LightBarTransitionsController;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * Dispatches events to {@link DarkReceiver}s about changes in darkness, tint area and dark
- * intensity
- */
-public interface DarkIconDispatcher extends Dumpable {
-
- void setIconsDarkArea(Rect r);
- LightBarTransitionsController getTransitionsController();
-
- void addDarkReceiver(DarkReceiver receiver);
- void addDarkReceiver(ImageView imageView);
-
- // Must have been previously been added through one of the addDarkReceive methods above.
- void removeDarkReceiver(DarkReceiver object);
- void removeDarkReceiver(ImageView object);
-
- // Used to reapply darkness on an object, must have previously been added through
- // addDarkReceiver.
- void applyDark(DarkReceiver object);
-
- /**
- * Dumpable interface
- */
- default void dump(FileDescriptor fd, PrintWriter pw, String[] args) {}
-
- int DEFAULT_ICON_TINT = Color.WHITE;
- Rect sTmpRect = new Rect();
- int[] sTmpInt2 = new int[2];
-
- /**
- * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
- * the screen {@param tintArea} in which to apply that tint
- */
- static int getTint(Rect tintArea, View view, int color) {
- if (isInArea(tintArea, view)) {
- return color;
- } else {
- return DEFAULT_ICON_TINT;
- }
- }
-
- /**
- * @return the dark intensity to apply to {@param view} depending on the desired dark
- * {@param intensity} and the screen {@param tintArea} in which to apply that intensity
- */
- static float getDarkIntensity(Rect tintArea, View view, float intensity) {
- if (isInArea(tintArea, view)) {
- return intensity;
- } else {
- return 0f;
- }
- }
-
- /**
- * @return true if more than half of the {@param view} area are in {@param area}, false
- * otherwise
- */
- static boolean isInArea(Rect area, View view) {
- if (area.isEmpty()) {
- return true;
- }
- sTmpRect.set(area);
- view.getLocationOnScreen(sTmpInt2);
- int left = sTmpInt2[0];
-
- int intersectStart = Math.max(left, area.left);
- int intersectEnd = Math.min(left + view.getWidth(), area.right);
- int intersectAmount = Math.max(0, intersectEnd - intersectStart);
-
- boolean coversFullStatusBar = area.top <= 0;
- boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
- return majorityOfWidth && coversFullStatusBar;
- }
-
- interface DarkReceiver {
- void onDarkChanged(Rect area, float darkIntensity, int tint);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 4a11754..54502e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -24,10 +24,10 @@
import android.view.MotionEvent;
import android.view.Surface;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.NavigationBarView;
-import com.android.systemui.statusbar.phone.StatusBar;
/**
* The "dead zone" consumes unintentional taps along the top edge of the navigation bar.
@@ -44,7 +44,7 @@
public static final int VERTICAL = 1; // Consume taps along the left edge.
private static final boolean CHATTY = true; // print to logcat when we eat a click
- private final StatusBar mStatusBar;
+ private final NavigationBarController mNavBarController;
private final NavigationBarView mNavigationBarView;
private boolean mShouldFlash;
@@ -58,6 +58,7 @@
private boolean mVertical;
private long mLastPokeTime;
private int mDisplayRotation;
+ private final int mDisplayId;
private final Runnable mDebugFlash = new Runnable() {
@Override
@@ -68,8 +69,8 @@
public DeadZone(NavigationBarView view) {
mNavigationBarView = view;
- mStatusBar = SysUiServiceProvider.getComponent(mNavigationBarView.getContext(),
- StatusBar.class);
+ mNavBarController = Dependency.get(NavigationBarController.class);
+ mDisplayId = view.getContext().getDisplayId();
onConfigurationChanged(HORIZONTAL);
}
@@ -133,7 +134,7 @@
if (DEBUG) {
Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
}
- if (mStatusBar != null) mStatusBar.touchAutoDim();
+ mNavBarController.touchAutoDim(mDisplayId);
int size = (int) getSize(event.getEventTime());
// In the vertical orientation consume taps along the left edge.
// In horizontal orientation consume taps along the top edge.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 2c756ce..d404982 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -33,6 +33,7 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
@@ -304,6 +305,10 @@
.setSubtype(mCode)
.addTaggedData(MetricsEvent.FIELD_NAV_ACTION, action)
.addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
+ // TODO(b/122195391): Added logs to make sure sysui is sending back button events
+ if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) {
+ Log.i(TAG, "Back button event: " + KeyEvent.actionToString(action));
+ }
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index b84f85b..122b094 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -16,13 +16,13 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
-import static com.android.systemui.ScreenDecorations.rectsToRegion;
+import static com.android.systemui.ScreenDecorations.rectsToRegion;
import static com.android.systemui.tuner.TunablePadding.FLAG_END;
import static com.android.systemui.tuner.TunablePadding.FLAG_START;
import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -87,7 +87,6 @@
mWindowManager = mock(WindowManager.class);
mView = spy(new StatusBarWindowView(mContext, null));
when(mStatusBar.getStatusBarWindow()).thenReturn(mView);
- when(mStatusBar.getNavigationBarWindow()).thenReturn(mView);
mContext.putComponent(StatusBar.class, mStatusBar);
Display display = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 9946317..926ff69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -17,7 +17,9 @@
package com.android.systemui.doze;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -37,6 +39,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerFake;
+import com.android.systemui.doze.DozeMachine.State;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -66,6 +69,7 @@
mMachine = mock(DozeMachine.class);
mHost = spy(new DozeHostFake());
mConfig = DozeConfigurationUtil.createMockConfig();
+ doReturn(false).when(mConfig).alwaysOnEnabled(anyInt());
mDockManagerFake = spy(new DockManagerFake());
mContext.putComponent(DockManager.class, mDockManagerFake);
@@ -75,7 +79,7 @@
}
@Test
- public void testDockEventListener_registerAndUnregister() throws Exception {
+ public void testDockEventListener_registerAndUnregister() {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
verify(mDockManagerFake).addListener(any());
@@ -86,55 +90,115 @@
}
@Test
- public void testOnEvent_dockingWhenDoze_requestPulse() throws Exception {
+ public void testOnEvent_dockedWhenDoze_requestPulse() {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
- mDockManagerFake.setDockEvent(DockManager.STATE_DOCKING);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED);
verify(mMachine).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
}
@Test
- public void testOnEvent_dockingWhenPausing_neverRequestPulse() throws Exception {
+ public void testOnEvent_dockedWhenDozeAoD_requestPulse() {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD_PAUSING);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD);
- mDockManagerFake.setDockEvent(DockManager.STATE_DOCKING);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED);
- verify(mMachine, never()).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
+ verify(mMachine).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
}
@Test
- public void testOnEvent_undockedWhenPulsing_requestPulseOut() throws Exception {
+ public void testOnEvent_dockedHideWhenPulsing_requestPulseOut() {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
+ when(mMachine.getState()).thenReturn(State.DOZE_PULSING);
when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_DOCKING);
- mDockManagerFake.setDockEvent(DockManager.STATE_UNDOCKING);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
verify(mHost).stopPulsing();
}
@Test
- public void testOnEvent_undockedWhenDoze_neverRequestPulseOut() throws Exception {
+ public void testOnEvent_undockedWhenPulsing_requestPulseOut() {
+ mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_PULSING);
+ when(mMachine.getPulseReason()).thenReturn(DozeLog.PULSE_REASON_DOCKING);
+
+ mDockManagerFake.setDockEvent(DockManager.STATE_NONE);
+
+ verify(mHost).stopPulsing();
+ }
+
+ @Test
+ public void testOnEvent_undockedWhenDoze_neverRequestPulseOut() {
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
- mDockManagerFake.setDockEvent(DockManager.STATE_UNDOCKING);
+ mDockManagerFake.setDockEvent(DockManager.STATE_NONE);
verify(mHost, never()).stopPulsing();
}
@Test
- public void testTransitionToDozeWhenDocking_RequestPulse() throws Exception {
+ public void testOnEvent_undockedWhenDozeAndEnabledAoD_requestDozeAoD() {
+ doReturn(true).when(mConfig).alwaysOnEnabled(anyInt());
mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
- mDockManagerFake.setDockEvent(DockManager.STATE_DOCKING);
- mDockHandler.transitionTo(DozeMachine.State.DOZE_AOD_PAUSING, DozeMachine.State.DOZE);
when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+ mDockManagerFake.setDockEvent(DockManager.STATE_NONE);
+
+ verify(mMachine).requestState(eq(State.DOZE_AOD));
+ }
+
+ @Test
+ public void testTransitionToDoze_whenDocked_requestPulse() {
+ mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.INITIALIZED);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+ mDockHandler.transitionTo(State.INITIALIZED, DozeMachine.State.DOZE);
+
TestableLooper.get(this).processAllMessages();
verify(mMachine).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
}
+
+ @Test
+ public void testTransitionToDozeAoD_whenDocked_requestPulse() {
+ mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.INITIALIZED);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD);
+ mDockHandler.transitionTo(State.INITIALIZED, DozeMachine.State.DOZE_AOD);
+
+ TestableLooper.get(this).processAllMessages();
+
+ verify(mMachine).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
+ }
+
+ @Test
+ public void testTransitionToDoze_whenDockedHide_neverRequestPulse() {
+ mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.INITIALIZED);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+ mDockHandler.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
+
+ verify(mMachine, never()).requestPulse(eq(DozeLog.PULSE_REASON_DOCKING));
+ }
+
+ @Test
+ public void testTransitionToDozeAoD_whenDockedHide_requestDoze() {
+ mDockHandler.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.INITIALIZED);
+ mDockManagerFake.setDockEvent(DockManager.STATE_DOCKED_HIDE);
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD);
+
+ mDockHandler.transitionTo(DozeMachine.State.INITIALIZED, State.DOZE_AOD);
+
+ verify(mMachine).requestState(eq(State.DOZE));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 7b96518..983ca83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -51,6 +52,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -72,9 +75,11 @@
// Dependency mocks:
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationListener mListener;
+ @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
private NotificationData.Entry mEntry;
private TestableNotificationLogger mLogger;
+ private NotificationEntryListener mNotificationEntryListener;
private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
@Before
@@ -94,6 +99,8 @@
mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
mEntryManager, mock(StatusBarStateController.class), mBarService);
mLogger.setUpWithContainer(mListContainer);
+ verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
+ mNotificationEntryListener = mEntryListenerCaptor.getValue();
}
@Test
@@ -152,6 +159,11 @@
verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
}
+ @Test
+ public void testHandleNullEntryOnEntryRemoved() {
+ mNotificationEntryListener.onEntryRemoved(null, "foobar", null, null, false, false);
+ }
+
private class TestableNotificationLogger extends NotificationLogger {
TestableNotificationLogger(NotificationListener notificationListener,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index d28f017..ecb0cf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -32,6 +32,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
@@ -44,6 +45,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.app.INotificationManager;
@@ -54,6 +56,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
@@ -69,6 +72,7 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -79,6 +83,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -177,6 +182,29 @@
() -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
}
+ class ImportanceChangeLogMaker implements ArgumentMatcher<LogMaker> {
+ private static final int CATEGORY = MetricsProto.MetricsEvent.ACTION_SAVE_IMPORTANCE;
+ private int mType, mSubtype;
+
+ ImportanceChangeLogMaker(int type, int subtype) {
+ mType = type;
+ mSubtype = subtype;
+ }
+ public boolean matches(LogMaker l) {
+ return (l.getCategory() == CATEGORY)
+ && (l.getType() == mType)
+ && (l.getSubtype() == mSubtype);
+ }
+
+ public String toString() {
+ return String.format("LogMaker(%d, %d, %d)", CATEGORY, mType, mSubtype);
+ }
+ }
+
+ private LogMaker importanceChangeLog(int type, int subtype) {
+ return argThat(new ImportanceChangeLogMaker(type, subtype));
+ }
+
@Test
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
@@ -475,7 +503,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
- verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
+ verifyZeroInteractions(mMetricsLogger);
}
@Test
@@ -484,7 +512,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
true, true, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
- verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
+ verify(mMetricsLogger).count(eq("HowCanNotifsBeRealIfAppsArent"), eq(1));
}
@Test
@@ -827,6 +855,9 @@
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
+ verify(mMetricsLogger).write(importanceChangeLog(
+ MetricsProto.MetricsEvent.TYPE_ACTION, IMPORTANCE_NONE - IMPORTANCE_LOW));
+
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> updated =
ArgumentCaptor.forClass(NotificationChannel.class);
@@ -860,6 +891,9 @@
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
+ verify(mMetricsLogger).write(importanceChangeLog(
+ MetricsProto.MetricsEvent.TYPE_ACTION, IMPORTANCE_NONE - IMPORTANCE_LOW));
+
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> updated =
ArgumentCaptor.forClass(NotificationChannel.class);
@@ -936,15 +970,14 @@
waitForUndoButton();
mNotificationInfo.findViewById(R.id.undo).performClick();
waitForStopButton();
- mNotificationInfo.handleCloseControls(true, false);
+ // mNotificationInfo.handleCloseControls doesn't get called by this interaction.
+
+ verify(mMetricsLogger).write(importanceChangeLog(
+ MetricsProto.MetricsEvent.TYPE_DISMISS, IMPORTANCE_NONE - IMPORTANCE_LOW));
mTestableLooper.processAllMessages();
- ArgumentCaptor<NotificationChannel> updated =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), eq(TEST_UID), updated.capture());
- assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
- assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
}
@Test
@@ -958,15 +991,11 @@
waitForUndoButton();
mNotificationInfo.findViewById(R.id.undo).performClick();
waitForStopButton();
- mNotificationInfo.handleCloseControls(true, false);
+ // mNotificationInfo.handleCloseControls doesn't get called by this code path
mTestableLooper.processAllMessages();
- ArgumentCaptor<NotificationChannel> updated =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), eq(TEST_UID), updated.capture());
- assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
- assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
+ verify(mMockINotificationManager, times(0)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 4f6329c..38d9ae7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -30,11 +30,11 @@
import android.widget.TextView;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import org.junit.Assert;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
index 76f57f0..40d5415 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
@@ -67,5 +67,4 @@
assertTrue(mTransitions.isLightsOut(BarTransitions.MODE_LIGHTS_OUT));
}
-
}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index 72b0156..4f95bc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -14,17 +14,14 @@
package com.android.systemui.statusbar.phone;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import android.graphics.Rect;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -32,15 +29,15 @@
import android.widget.LinearLayout;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.statusbar.StatusIconDisplayable;
+import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index e80694c..18ead90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -82,6 +82,7 @@
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -196,6 +197,7 @@
mDreamManager);
mDependency.injectTestDependency(NotificationInterruptionStateProvider.class,
mNotificationInterruptionStateProvider);
+ mDependency.injectMockDependency(NavigationBarController.class);
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -245,7 +247,7 @@
mock(StatusBarWindowController.class), mock(NotificationIconAreaController.class),
mDozeScrimController, mock(NotificationShelf.class),
mLockscreenUserManager, mCommandQueue, mNotificationPresenter,
- mock(BubbleController.class));
+ mock(BubbleController.class), mock(NavigationBarController.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
SystemUIFactory.getInstance().getRootComponent()
@@ -695,7 +697,8 @@
NotificationLockscreenUserManager notificationLockscreenUserManager,
CommandQueue commandQueue,
NotificationPresenter notificationPresenter,
- BubbleController bubbleController) {
+ BubbleController bubbleController,
+ NavigationBarController navBarController) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -726,6 +729,7 @@
mPresenter = notificationPresenter;
mGestureWakeLock = mock(PowerManager.WakeLock.class);
mBubbleController = bubbleController;
+ mNavigationBarController = navBarController;
}
private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/packages/overlays/IconShapeRoundedRectOverlay/res/values/config.xml b/packages/overlays/IconShapeRoundedRectOverlay/res/values/config.xml
index f024615..138c283 100644
--- a/packages/overlays/IconShapeRoundedRectOverlay/res/values/config.xml
+++ b/packages/overlays/IconShapeRoundedRectOverlay/res/values/config.xml
@@ -18,7 +18,7 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
- <string name="config_icon_mask" translatable="false">"M50,0L92,0C96.42,0 100,4.58 100 8L100,92C100, 96.42 96.42 100 92 100L8 100C4.58, 100 0 96.42 0 92L0 8 C 0 4.42 4.42 0 8 0L50 0Z"</string>
+ <string name="config_icon_mask" translatable="false">"M50,0L88,0 C94.4,0 100,5.4 100 12 L100,88 C100,94.6 94.6 100 88 100 L12,100 C5.4,100 0,94.6 0,88 L0 12 C0 5.4 5.4 0 12 0 L50,0 Z"</string>
<!-- Flag indicating whether round icons should be parsed from the application manifest. -->
<bool name="config_useRoundIcon">false</bool>
diff --git a/packages/overlays/IconShapeTeardropOverlay/res/values/config.xml b/packages/overlays/IconShapeTeardropOverlay/res/values/config.xml
index 43ad04d..818e696 100644
--- a/packages/overlays/IconShapeTeardropOverlay/res/values/config.xml
+++ b/packages/overlays/IconShapeTeardropOverlay/res/values/config.xml
@@ -18,7 +18,7 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Specifies the path that is used by AdaptiveIconDrawable class to crop launcher icons. -->
- <string name="config_icon_mask" translatable="false">"M50,0A50,50,0,0 1 100,50 L100,85 A15,15,0,0 1 85,100 L50,100 A50,50,0,0 1 50,0z"</string>
+ <string name="config_icon_mask" translatable="false">"M50,0 C77.6,0 100,22.4 100,50 L100,88 C100,94.6 94.6,100 88,100 L50,100 C22.4 100 0 77.6 0 50C0 22.4 22.4 0 50 0 Z"</string>
<!-- Flag indicating whether round icons should be parsed from the application manifest. -->
<bool name="config_useRoundIcon">false</bool>
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0e9b407..0348f2b 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -64,9 +64,11 @@
import android.os.SystemClock;
import android.service.autofill.AutofillFieldClassificationService.Scores;
import android.service.autofill.AutofillService;
+import android.service.autofill.CompositeUserData;
import android.service.autofill.Dataset;
import android.service.autofill.FieldClassification;
import android.service.autofill.FieldClassification.Match;
+import android.service.autofill.FieldClassificationUserData;
import android.service.autofill.FillContext;
import android.service.autofill.FillRequest;
import android.service.autofill.FillResponse;
@@ -1237,11 +1239,16 @@
return;
}
+ // Merge UserData if necessary.
+ // Fields in packageUserData will override corresponding fields in genericUserData.
+ final UserData genericUserData = mService.getUserData();
final UserData packageUserData = lastResponse.getUserData();
-
- final UserData userData;
- if (packageUserData != null) {
- // Replace default userData
+ final FieldClassificationUserData userData;
+ if (packageUserData == null && genericUserData == null) {
+ userData = null;
+ } else if (packageUserData != null && genericUserData != null) {
+ userData = new CompositeUserData(genericUserData, packageUserData);
+ } else if (packageUserData != null) {
userData = packageUserData;
} else {
userData = mService.getUserData();
@@ -1396,7 +1403,8 @@
@NonNull ArrayList<String> changedDatasetIds,
@NonNull ArrayList<AutofillId> manuallyFilledFieldIds,
@NonNull ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
- @NonNull UserData userData, @NonNull Collection<ViewState> viewStates) {
+ @NonNull FieldClassificationUserData userData,
+ @NonNull Collection<ViewState> viewStates) {
final String[] userValues = userData.getValues();
final String[] categoryIds = userData.getCategoryIds();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 7049744..8b07db7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -36,7 +36,6 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.Environment;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -50,11 +49,7 @@
import com.android.server.SystemConfig;
import com.android.server.SystemService;
-import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Set;
@@ -72,10 +67,6 @@
public static final boolean MORE_DEBUG = false;
public static final boolean DEBUG_SCHEDULING = true;
- // File containing backup-enabled state. Contains a single byte to denote enabled status.
- // Nonzero is enabled; file missing or a zero byte is disabled.
- private static final String BACKUP_ENABLE_FILE = "backup_enabled";
-
// The published binder is a singleton Trampoline object that calls through to the proper code.
// This indirection lets us turn down the heavy implementation object on the fly without
// disturbing binders that have been cached elsewhere in the system.
@@ -150,7 +141,8 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
try {
// TODO(b/121198604): Make enable file per-user and clean up indirection.
- mTrampoline.setBackupEnabledForUser(userId, readBackupEnableState(userId));
+ mTrampoline.setBackupEnabledForUser(
+ userId, UserBackupManagerFilePersistedSettings.readBackupEnableState(userId));
} catch (RemoteException e) {
// Can't happen, it's a local object.
}
@@ -773,44 +765,6 @@
}
}
- private static boolean readBackupEnableState(int userId) {
- File base = new File(Environment.getDataDirectory(), "backup");
- File enableFile = new File(base, BACKUP_ENABLE_FILE);
- if (enableFile.exists()) {
- try (FileInputStream fin = new FileInputStream(enableFile)) {
- int state = fin.read();
- return state != 0;
- } catch (IOException e) {
- // can't read the file; fall through to assume disabled
- Slog.e(TAG, "Cannot read enable state; assuming disabled");
- }
- } else {
- if (DEBUG) {
- Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
- }
- }
- return false;
- }
-
- static void writeBackupEnableState(boolean enable, int userId) {
- File base = new File(Environment.getDataDirectory(), "backup");
- File enableFile = new File(base, BACKUP_ENABLE_FILE);
- File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
- try (FileOutputStream fout = new FileOutputStream(stage)) {
- fout.write(enable ? 1 : 0);
- fout.close();
- stage.renameTo(enableFile);
- // will be synced immediately by the try-with-resources call to close()
- } catch (IOException | RuntimeException e) {
- Slog.e(
- TAG,
- "Unable to record backup enable state; reverting to disabled: "
- + e.getMessage());
- enableFile.delete();
- stage.delete();
- }
- }
-
/** Implementation to receive lifecycle event callbacks for system services. */
public static final class Lifecycle extends SystemService {
public Lifecycle(Context context) {
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java b/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java
new file mode 100644
index 0000000..6a1de63
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerFilePersistedSettings.java
@@ -0,0 +1,78 @@
+/*
+ * 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.backup;
+
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
+
+import android.util.Slog;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/** User settings which are persisted across reboots. */
+final class UserBackupManagerFilePersistedSettings {
+ // File containing backup-enabled state. Contains a single byte to denote enabled status.
+ // Nonzero is enabled; file missing or a zero byte is disabled.
+ private static final String BACKUP_ENABLE_FILE = "backup_enabled";
+
+ static boolean readBackupEnableState(int userId) {
+ return readBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId));
+ }
+
+ static void writeBackupEnableState(int userId, boolean enable) {
+ writeBackupEnableState(UserBackupManagerFiles.getBaseStateDir(userId), enable);
+ }
+
+ private static boolean readBackupEnableState(File baseDir) {
+ File enableFile = new File(baseDir, BACKUP_ENABLE_FILE);
+ if (enableFile.exists()) {
+ try (FileInputStream fin = new FileInputStream(enableFile)) {
+ int state = fin.read();
+ return state != 0;
+ } catch (IOException e) {
+ // can't read the file; fall through to assume disabled
+ Slog.e(TAG, "Cannot read enable state; assuming disabled");
+ }
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
+ }
+ }
+ return false;
+ }
+
+ private static void writeBackupEnableState(File baseDir, boolean enable) {
+ File enableFile = new File(baseDir, BACKUP_ENABLE_FILE);
+ File stage = new File(baseDir, BACKUP_ENABLE_FILE + "-stage");
+ try (FileOutputStream fout = new FileOutputStream(stage)) {
+ fout.write(enable ? 1 : 0);
+ fout.close();
+ stage.renameTo(enableFile);
+ // will be synced immediately by the try-with-resources call to close()
+ } catch (IOException | RuntimeException e) {
+ Slog.e(
+ TAG,
+ "Unable to record backup enable state; reverting to disabled: "
+ + e.getMessage());
+ enableFile.delete();
+ stage.delete();
+ }
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java b/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java
new file mode 100644
index 0000000..a0feaf9
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerFiles.java
@@ -0,0 +1,45 @@
+/*
+ * 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.backup;
+
+import android.os.Environment;
+
+import java.io.File;
+
+/** Directories used for user specific backup/restore persistent state and book-keeping. */
+public final class UserBackupManagerFiles {
+ // Name of the directories the service stores bookkeeping data under.
+ private static final String BACKUP_PERSISTENT_DIR = "backup";
+ private static final String BACKUP_STAGING_DIR = "backup_stage";
+
+ static File getBaseStateDir(int userId) {
+ // TODO (b/120424138) this should be per user
+ return new File(Environment.getDataDirectory(), BACKUP_PERSISTENT_DIR);
+ }
+
+ static File getDataDir(int userId) {
+ // TODO (b/120424138) this should be per user
+ // This dir on /cache is managed directly in init.rc
+ return new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
+ }
+
+ /** Directory used by full backup engine to store state. */
+ public static File getFullBackupEngineFilesDir(int userId) {
+ // TODO (b/120424138) this should be per user
+ return new File("/data/system");
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 2e41443..6425508 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -70,7 +70,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -164,17 +163,9 @@
/** System service that performs backup/restore operations. */
public class UserBackupManagerService {
- // File containing backup-enabled state. Contains a single byte;
- // nonzero == enabled. File missing or contains a zero byte == disabled.
- private static final String BACKUP_ENABLE_FILE = "backup_enabled";
-
// Persistently track the need to do a full init.
private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
- // Name of the directories the service stores bookkeeping data under.
- private static final String BACKUP_PERSISTENT_DIR = "backup";
- private static final String BACKUP_STAGING_DIR = "backup_stage";
-
// System-private key used for backing up an app's widget state. Must
// begin with U+FFxx by convention (we reserve all keys starting
// with U+FF00 or higher for system use).
@@ -354,9 +345,9 @@
final AtomicInteger mNextToken = new AtomicInteger();
// Where we keep our journal files and other bookkeeping.
- private File mBaseStateDir;
- private File mDataDir;
- private File mJournalDir;
+ private final File mBaseStateDir;
+ private final File mDataDir;
+ private final File mJournalDir;
@Nullable
private DataChangedJournal mJournal;
private File mFullBackupScheduleFile;
@@ -395,10 +386,8 @@
TransportManager transportManager =
new TransportManager(context, transportWhitelist, currentTransport);
- File baseStateDir = new File(Environment.getDataDirectory(), BACKUP_PERSISTENT_DIR);
-
- // This dir on /cache is managed directly in init.rc
- File dataDir = new File(Environment.getDownloadCacheDirectory(), BACKUP_STAGING_DIR);
+ File baseStateDir = UserBackupManagerFiles.getBaseStateDir(userId);
+ File dataDir = UserBackupManagerFiles.getDataDir(userId);
return createAndInitializeService(
userId, context, trampoline, backupThread, baseStateDir, dataDir, transportManager);
@@ -726,18 +715,10 @@
return mBaseStateDir;
}
- public void setBaseStateDir(File baseStateDir) {
- mBaseStateDir = baseStateDir;
- }
-
public File getDataDir() {
return mDataDir;
}
- public void setDataDir(File dataDir) {
- mDataDir = dataDir;
- }
-
@Nullable
public DataChangedJournal getJournal() {
return mJournal;
@@ -2735,8 +2716,7 @@
try {
boolean wasEnabled = mEnabled;
synchronized (this) {
- // TODO(b/118520567): Clean up writing backup enabled logic.
- BackupManagerService.writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
+ UserBackupManagerFilePersistedSettings.writeBackupEnableState(mUserId, enable);
mEnabled = enable;
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 5e92339..45ca2af 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -24,6 +24,7 @@
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP_WAIT;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+import android.annotation.UserIdInt;
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupTransport;
@@ -40,6 +41,7 @@
import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupRestoreTask;
+import com.android.server.backup.UserBackupManagerFiles;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.remote.RemoteCall;
import com.android.server.backup.utils.FullBackupUtils;
@@ -66,6 +68,7 @@
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
class FullBackupRunner implements Runnable {
+ private final @UserIdInt int mUserId;
private final PackageManager mPackageManager;
private final PackageInfo mPackage;
private final IBackupAgent mAgent;
@@ -81,13 +84,15 @@
int token,
boolean includeApks)
throws IOException {
+ // TODO: http://b/22388012
+ mUserId = UserHandle.USER_SYSTEM;
mPackageManager = backupManagerService.getPackageManager();
mPackage = packageInfo;
mAgent = agent;
mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor());
mToken = token;
mIncludeApks = includeApks;
- mFilesDir = new File("/data/system");
+ mFilesDir = UserBackupManagerFiles.getFullBackupEngineFilesDir(mUserId);
}
@Override
@@ -114,10 +119,8 @@
manifestFile.delete();
// Write widget data.
- // TODO: http://b/22388012
byte[] widgetData =
- AppWidgetBackupBridge.getWidgetState(
- packageName, UserHandle.USER_SYSTEM);
+ AppWidgetBackupBridge.getWidgetState(packageName, mUserId);
if (widgetData != null && widgetData.length > 0) {
File metadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
appMetadataBackupWriter.backupWidget(
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
new file mode 100644
index 0000000..06dc918
--- /dev/null
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -0,0 +1,572 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Monitors the health of packages on the system and notifies interested observers when packages
+ * fail. All registered observers will be notified until an observer takes a mitigation action.
+ */
+public class PackageWatchdog {
+ private static final String TAG = "PackageWatchdog";
+ // Duration to count package failures before it resets to 0
+ private static final int TRIGGER_DURATION_MS = 60000;
+ // Number of package failures within the duration above before we notify observers
+ private static final int TRIGGER_FAILURE_COUNT = 5;
+ private static final int DB_VERSION = 1;
+ private static final String TAG_PACKAGE_WATCHDOG = "package-watchdog";
+ private static final String TAG_PACKAGE = "package";
+ private static final String TAG_OBSERVER = "observer";
+ private static final String ATTR_VERSION = "version";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DURATION = "duration";
+ private static final int MESSAGE_SAVE_FILE = 1;
+
+ private static PackageWatchdog sPackageWatchdog;
+
+ private final Object mLock = new Object();
+ // System server context
+ private final Context mContext;
+ // Handler to run package cleanup runnables
+ private final Handler mTimerHandler;
+ private final HandlerThread mIoThread = new HandlerThread("package_watchdog_io",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ private final Handler mIoHandler;
+ // Maps observer names to package observers that have been registered since the last boot
+ @GuardedBy("mLock")
+ final Map<String, PackageHealthObserver> mRegisteredObservers = new ArrayMap<>();
+ // Maps observer names to internal observers (registered or not) loaded from file
+ @GuardedBy("mLock")
+ final Map<String, ObserverInternal> mAllObservers = new ArrayMap<>();
+ // /data/system/ directory
+ private final File mSystemDir = new File(Environment.getDataDirectory(), "system");
+ // File containing the XML data of monitored packages
+ private final AtomicFile mPolicyFile =
+ new AtomicFile(new File(mSystemDir, "package-watchdog.xml"));
+ // Runnable to prune monitored packages that have expired
+ private final Runnable mPackageCleanup;
+ // Last SystemClock#uptimeMillis a package clean up was executed.
+ // 0 if mPackageCleanup not running.
+ private long mUptimeAtLastRescheduleMs;
+ // Duration a package cleanup was last scheduled for.
+ // 0 if mPackageCleanup not running.
+ private long mDurationAtLastReschedule;
+
+ private PackageWatchdog(Context context) {
+ mContext = context;
+ mTimerHandler = new Handler(Looper.myLooper());
+ mIoThread.start();
+ mIoHandler = new IoHandler(mIoThread.getLooper());
+ mPackageCleanup = this::rescheduleCleanup;
+ loadFromFile();
+ }
+
+ /** Creates or gets singleton instance of PackageWatchdog. */
+ public static synchronized PackageWatchdog getInstance(Context context) {
+ if (sPackageWatchdog == null) {
+ sPackageWatchdog = new PackageWatchdog(context);
+ }
+ return sPackageWatchdog;
+ }
+
+ /**
+ * Registers {@code observer} to listen for package failures
+ *
+ * <p>Observers are expected to call this on boot. It does not specify any packages but
+ * it will resume observing any packages requested from a previous boot.
+ */
+ public void registerHealthObserver(PackageHealthObserver observer) {
+ synchronized (mLock) {
+ mRegisteredObservers.put(observer.getName(), observer);
+ if (mDurationAtLastReschedule == 0) {
+ // Nothing running, schedule
+ rescheduleCleanup();
+ }
+ }
+ }
+
+ /**
+ * Starts observing the health of the {@code packages} for {@code observer} and notifies
+ * {@code observer} of any package failures within the monitoring duration.
+ *
+ * <p>If {@code observer} is already monitoring a package in {@code packageNames},
+ * the monitoring window of that package will be reset to {@code hours}.
+ *
+ * @throws IllegalArgumentException if {@code packageNames} is empty
+ * or {@code hours} is less than 1
+ */
+ public void startObservingHealth(PackageHealthObserver observer, List<String> packageNames,
+ int hours) {
+ if (packageNames.isEmpty() || hours < 1) {
+ throw new IllegalArgumentException("Observation not started, no packages specified"
+ + "or invalid hours");
+ }
+ long durationMs = TimeUnit.HOURS.toMillis(hours);
+ List<MonitoredPackage> packages = new ArrayList<>();
+ for (String packageName : packageNames) {
+ packages.add(new MonitoredPackage(packageName, durationMs));
+ }
+ synchronized (mLock) {
+ ObserverInternal oldObserver = mAllObservers.get(observer.getName());
+ if (oldObserver == null) {
+ Slog.d(TAG, observer.getName() + " started monitoring health of packages "
+ + packageNames);
+ mAllObservers.put(observer.getName(),
+ new ObserverInternal(observer.getName(), packages));
+ } else {
+ Slog.d(TAG, observer.getName() + " added the following packages to monitor "
+ + packageNames);
+ oldObserver.updatePackages(packages);
+ }
+ }
+ registerHealthObserver(observer);
+ // Always reschedule because we may need to expire packages
+ // earlier than we are already scheduled for
+ rescheduleCleanup();
+ sendIoMessage(MESSAGE_SAVE_FILE);
+ }
+
+ /**
+ * Unregisters {@code observer} from listening to package failure.
+ * Additionally, this stops observing any packages that may have previously been observed
+ * even from a previous boot.
+ */
+ public void unregisterHealthObserver(PackageHealthObserver observer) {
+ synchronized (mLock) {
+ mAllObservers.remove(observer.getName());
+ mRegisteredObservers.remove(observer.getName());
+ }
+ sendIoMessage(MESSAGE_SAVE_FILE);
+ }
+
+ // TODO(zezeozue:) Accept current versionCodes of failing packages?
+ /**
+ * Called when a process fails either due to a crash or ANR.
+ *
+ * <p>All registered observers for the packages contained in the process will be notified in
+ * order of priority unitl an observer signifies that it has taken action and other observers
+ * should not notified.
+ *
+ * <p>This method could be called frequently if there is a severe problem on the device.
+ */
+ public void onPackageFailure(String[] packages) {
+ synchronized (mLock) {
+ if (mRegisteredObservers.isEmpty()) {
+ return;
+ }
+ for (String packageName : packages) {
+ for (ObserverInternal observer : mAllObservers.values()) {
+ if (observer.onPackageFailure(packageName)) {
+ PackageHealthObserver activeObserver =
+ mRegisteredObservers.get(observer.mName);
+ if (activeObserver != null
+ && activeObserver.onHealthCheckFailed(packageName)) {
+ // Observer has handled, do not notify other observers
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // TODO(zezeozue): Optimize write? Maybe only write a separate smaller file?
+ // This currently adds about 7ms extra to shutdown thread
+ /** Writes the package information to file during shutdown. */
+ public void writeNow() {
+ if (!mAllObservers.isEmpty()) {
+ mIoHandler.removeMessages(MESSAGE_SAVE_FILE);
+ pruneObservers(SystemClock.uptimeMillis() - mUptimeAtLastRescheduleMs);
+ saveToFile();
+ Slog.i(TAG, "Last write to update package durations");
+ }
+ }
+
+ /** Register instances of this interface to receive notifications on package failure. */
+ public interface PackageHealthObserver {
+ /**
+ * Called when health check fails for the {@code packages}.
+ * @return {@code true} if action was taken and other observers should not be notified of
+ * this failure, {@code false} otherwise.
+ */
+ boolean onHealthCheckFailed(String packageName);
+
+ // TODO(zezeozue): Ensure uniqueness?
+ /**
+ * Identifier for the observer, should not change across device updates otherwise the
+ * watchdog may drop observing packages with the old name.
+ */
+ String getName();
+ }
+
+ /** Reschedules handler to prune expired packages from observers. */
+ private void rescheduleCleanup() {
+ synchronized (mLock) {
+ long nextDurationToScheduleMs = getEarliestPackageExpiryLocked();
+ if (nextDurationToScheduleMs == Long.MAX_VALUE) {
+ Slog.i(TAG, "No monitored packages, ending package cleanup");
+ mDurationAtLastReschedule = 0;
+ mUptimeAtLastRescheduleMs = 0;
+ return;
+ }
+ long uptimeMs = SystemClock.uptimeMillis();
+ // O if mPackageCleanup not running
+ long elapsedDurationMs = mUptimeAtLastRescheduleMs == 0
+ ? 0 : uptimeMs - mUptimeAtLastRescheduleMs;
+ // O if mPackageCleanup not running
+ long remainingDurationMs = mDurationAtLastReschedule - elapsedDurationMs;
+
+ if (mUptimeAtLastRescheduleMs == 0 || nextDurationToScheduleMs < remainingDurationMs) {
+ // First schedule or an earlier reschedule
+ pruneObservers(elapsedDurationMs);
+ mTimerHandler.removeCallbacks(mPackageCleanup);
+ mTimerHandler.postDelayed(mPackageCleanup, nextDurationToScheduleMs);
+ mDurationAtLastReschedule = nextDurationToScheduleMs;
+ mUptimeAtLastRescheduleMs = uptimeMs;
+ }
+ }
+ }
+
+ /**
+ * Returns the earliest time a package should expire.
+ * @returns Long#MAX_VALUE if there are no observed packages.
+ */
+ private long getEarliestPackageExpiryLocked() {
+ long shortestDurationMs = Long.MAX_VALUE;
+ for (ObserverInternal observer : mAllObservers.values()) {
+ for (MonitoredPackage p : observer.mPackages.values()) {
+ if (p.mDurationMs < shortestDurationMs) {
+ shortestDurationMs = p.mDurationMs;
+ }
+ }
+ }
+ Slog.v(TAG, "Earliest package time is " + shortestDurationMs);
+ return shortestDurationMs;
+ }
+
+ /**
+ * Removes {@code elapsedMs} milliseconds from all durations on monitored packages.
+ * Discards expired packages and discards observers without any packages.
+ */
+ private void pruneObservers(long elapsedMs) {
+ if (elapsedMs == 0) {
+ return;
+ }
+ synchronized (mLock) {
+ Slog.d(TAG, "Removing expired packages after " + elapsedMs + "ms");
+ Iterator<ObserverInternal> it = mAllObservers.values().iterator();
+ while (it.hasNext()) {
+ ObserverInternal observer = it.next();
+ if (!observer.updateMonitoringDurations(elapsedMs)) {
+ Slog.i(TAG, "Discarding observer " + observer.mName + ". All packages expired");
+ it.remove();
+ }
+ }
+ }
+ sendIoMessage(MESSAGE_SAVE_FILE);
+ }
+
+ /**
+ * Loads mAllObservers from file.
+ *
+ * <p>Note that this is <b>not</b> thread safe and should only called be called
+ * from the constructor.
+ */
+ private void loadFromFile() {
+ InputStream infile = null;
+ mAllObservers.clear();
+ try {
+ infile = mPolicyFile.openRead();
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(infile, StandardCharsets.UTF_8.name());
+ XmlUtils.beginDocument(parser, TAG_PACKAGE_WATCHDOG);
+ int outerDepth = parser.getDepth();
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ ObserverInternal observer = ObserverInternal.read(parser);
+ if (observer != null) {
+ mAllObservers.put(observer.mName, observer);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Nothing to monitor
+ } catch (IOException e) {
+ Log.wtf(TAG, "Unable to read monitored packages", e);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Unable to parse monitored package windows", e);
+ } catch (XmlPullParserException e) {
+ Log.wtf(TAG, "Unable to parse monitored packages", e);
+ } finally {
+ IoUtils.closeQuietly(infile);
+ }
+ }
+
+ /**
+ * Persists mAllObservers to file and ignores threshold information.
+ *
+ * <p>Note that this is <b>not</b> thread safe and should only be called on the
+ * single threaded IoHandler.
+ */
+ private boolean saveToFile() {
+ FileOutputStream stream;
+ try {
+ stream = mPolicyFile.startWrite();
+ } catch (IOException e) {
+ Slog.w(TAG, "Cannot update monitored packages", e);
+ return false;
+ }
+
+ try {
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+ out.startTag(null, TAG_PACKAGE_WATCHDOG);
+ out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
+ for (ObserverInternal observer : mAllObservers.values()) {
+ observer.write(out);
+ }
+ out.endTag(null, TAG_PACKAGE_WATCHDOG);
+ out.endDocument();
+ mPolicyFile.finishWrite(stream);
+ return true;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save monitored packages, restoring backup", e);
+ mPolicyFile.failWrite(stream);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(stream);
+ }
+ }
+
+ private void sendIoMessage(int what) {
+ if (!mIoHandler.hasMessages(what)) {
+ Message m = Message.obtain(mIoHandler, what);
+ mIoHandler.sendMessage(m);
+ }
+ }
+
+ /**
+ * Represents an observer monitoring a set of packages along with the failure thresholds for
+ * each package.
+ */
+ static class ObserverInternal {
+ public final String mName;
+ public final ArrayMap<String, MonitoredPackage> mPackages;
+
+ ObserverInternal(String name, List<MonitoredPackage> packages) {
+ mName = name;
+ mPackages = new ArrayMap<>();
+ updatePackages(packages);
+ }
+
+ /**
+ * Writes important details to file. Doesn't persist any package failure thresholds.
+ *
+ * <p>Note that this method is <b>not</b> thread safe. It should only be called from
+ * #saveToFile which runs on a single threaded handler.
+ */
+ public boolean write(XmlSerializer out) {
+ try {
+ out.startTag(null, TAG_OBSERVER);
+ out.attribute(null, ATTR_NAME, mName);
+ for (int i = 0; i < mPackages.size(); i++) {
+ MonitoredPackage p = mPackages.valueAt(i);
+ out.startTag(null, TAG_PACKAGE);
+ out.attribute(null, ATTR_NAME, p.mName);
+ out.attribute(null, ATTR_DURATION, String.valueOf(p.mDurationMs));
+ out.endTag(null, TAG_PACKAGE);
+ }
+ out.endTag(null, TAG_OBSERVER);
+ return true;
+ } catch (IOException e) {
+ Slog.w(TAG, "Cannot save observer", e);
+ return false;
+ }
+ }
+
+ public void updatePackages(List<MonitoredPackage> packages) {
+ synchronized (mName) {
+ for (MonitoredPackage p : packages) {
+ mPackages.put(p.mName, p);
+ }
+ }
+ }
+
+ /**
+ * Reduces the monitoring durations of all packages observed by this observer by
+ * {@code elapsedMs}. If any duration is less than 0, the package is removed from
+ * observation.
+ *
+ * @returns {@code true} if there are still packages to be observed, {@code false} otherwise
+ */
+ public boolean updateMonitoringDurations(long elapsedMs) {
+ List<MonitoredPackage> packages = new ArrayList<>();
+ synchronized (mName) {
+ Iterator<MonitoredPackage> it = mPackages.values().iterator();
+ while (it.hasNext()) {
+ MonitoredPackage p = it.next();
+ long newDuration = p.mDurationMs - elapsedMs;
+ if (newDuration > 0) {
+ p.mDurationMs = newDuration;
+ } else {
+ it.remove();
+ }
+ }
+ return !mPackages.isEmpty();
+ }
+ }
+
+ /**
+ * Increments failure counts of {@code packageName}.
+ * @returns {@code true} if failure threshold is exceeded, {@code false} otherwise
+ */
+ public boolean onPackageFailure(String packageName) {
+ synchronized (mName) {
+ MonitoredPackage p = mPackages.get(packageName);
+ if (p != null) {
+ return p.onFailure();
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns one ObserverInternal from the {@code parser} and advances its state.
+ *
+ * <p>Note that this method is <b>not</b> thread safe. It should only be called from
+ * #loadFromFile which in turn is only called on construction of the
+ * singleton PackageWatchdog.
+ **/
+ public static ObserverInternal read(XmlPullParser parser) {
+ String observerName = null;
+ if (TAG_OBSERVER.equals(parser.getName())) {
+ observerName = parser.getAttributeValue(null, ATTR_NAME);
+ if (TextUtils.isEmpty(observerName)) {
+ return null;
+ }
+ }
+ List<MonitoredPackage> packages = new ArrayList<>();
+ int innerDepth = parser.getDepth();
+ try {
+ while (XmlUtils.nextElementWithin(parser, innerDepth)) {
+ if (TAG_PACKAGE.equals(parser.getName())) {
+ String packageName = parser.getAttributeValue(null, ATTR_NAME);
+ long duration = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_DURATION));
+ if (!TextUtils.isEmpty(packageName)) {
+ packages.add(new MonitoredPackage(packageName, duration));
+ }
+ }
+ }
+ } catch (IOException e) {
+ return null;
+ } catch (XmlPullParserException e) {
+ return null;
+ }
+ if (packages.isEmpty()) {
+ return null;
+ }
+ return new ObserverInternal(observerName, packages);
+ }
+ }
+
+ /** Represents a package along with the time it should be monitored for. */
+ static class MonitoredPackage {
+ public final String mName;
+ // System uptime duration to monitor package
+ public long mDurationMs;
+ // System uptime of first package failure
+ private long mUptimeStartMs;
+ // Number of failures since mUptimeStartMs
+ private int mFailures;
+
+ MonitoredPackage(String name, long durationMs) {
+ mName = name;
+ mDurationMs = durationMs;
+ }
+
+ /**
+ * Increment package failures or resets failure count depending on the last package failure.
+ *
+ * @return {@code true} if failure count exceeds a threshold, {@code false} otherwise
+ */
+ public synchronized boolean onFailure() {
+ final long now = SystemClock.uptimeMillis();
+ final long duration = now - mUptimeStartMs;
+ if (duration > TRIGGER_DURATION_MS) {
+ // TODO(zezeozue): Reseting to 1 is not correct
+ // because there may be more than 1 failure in the last trigger window from now
+ // This is the RescueParty impl, will leave for now
+ mFailures = 1;
+ mUptimeStartMs = now;
+ } else {
+ mFailures++;
+ }
+ return mFailures >= TRIGGER_FAILURE_COUNT;
+ }
+ }
+
+ private class IoHandler extends Handler {
+ IoHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_SAVE_FILE:
+ saveToFile();
+ break;
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index e80e9e1..1aeb689 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -91,6 +91,7 @@
"/system/bin/mediaserver",
"/system/bin/sdcard",
"/system/bin/surfaceflinger",
+ "/system/bin/vold",
"media.extractor", // system/bin/mediaextractor
"media.metrics", // system/bin/mediametrics
"media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1a5dd90..16c236e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -336,6 +336,7 @@
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.NetworkManagementInternal;
+import com.android.server.PackageWatchdog;
import com.android.server.RescueParty;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
@@ -587,6 +588,7 @@
public final PendingIntentController mPendingIntentController;
final AppErrors mAppErrors;
+ final PackageWatchdog mPackageWatchdog;
/**
* Indicates the maximum time spent waiting for the network rules to get updated.
@@ -2209,6 +2211,7 @@
mContext = mInjector.getContext();
mUiContext = null;
mAppErrors = null;
+ mPackageWatchdog = null;
mActiveUids = new ActiveUids(this, false /* postChangesToAtm */);
mAppOpsService = mInjector.getAppOpsService(null /* file */, null /* handler */);
mBatteryStatsService = null;
@@ -2275,7 +2278,8 @@
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
- mAppErrors = new AppErrors(mUiContext, this);
+ mPackageWatchdog = PackageWatchdog.getInstance(mUiContext);
+ mAppErrors = new AppErrors(mUiContext, this, mPackageWatchdog);
mActiveUids = new ActiveUids(this, true /* postChangesToAtm */);
final File systemDir = SystemServiceManager.ensureSystemDir();
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 1c1daff..a634b57 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -53,6 +53,7 @@
import com.android.internal.app.ProcessMap;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.server.PackageWatchdog;
import com.android.server.RescueParty;
import com.android.server.wm.WindowProcessController;
@@ -69,6 +70,7 @@
private final ActivityManagerService mService;
private final Context mContext;
+ private final PackageWatchdog mPackageWatchdog;
private ArraySet<String> mAppsNotReportingCrashes;
@@ -93,10 +95,11 @@
private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
- AppErrors(Context context, ActivityManagerService service) {
+ AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
context.assertRuntimeOverlayThemable();
mService = service;
mContext = context;
+ mPackageWatchdog = watchdog;
}
void writeToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
@@ -400,10 +403,16 @@
longMsg = shortMsg;
}
- // If a persistent app is stuck in a crash loop, the device isn't very
- // usable, so we want to consider sending out a rescue party.
- if (r != null && r.isPersistent()) {
- RescueParty.notePersistentAppCrash(mContext, r.uid);
+ if (r != null) {
+ if (r.isPersistent()) {
+ // If a persistent app is stuck in a crash loop, the device isn't very
+ // usable, so we want to consider sending out a rescue party.
+ RescueParty.notePersistentAppCrash(mContext, r.uid);
+ } else {
+ // If a non-persistent app is stuck in crash loop, we want to inform
+ // the package watchdog, maybe an update or experiment can be rolled back.
+ mPackageWatchdog.onPackageFailure(r.getPackageList());
+ }
}
final int relaunchReason = r != null
@@ -821,6 +830,7 @@
void handleShowAnrUi(Message msg) {
Dialog dialogToShow = null;
+ String[] packageList = null;
synchronized (mService) {
AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
final ProcessRecord proc = data.proc;
@@ -828,6 +838,9 @@
Slog.e(TAG, "handleShowAnrUi: proc is null");
return;
}
+ if (!proc.isPersistent()) {
+ packageList = proc.getPackageList();
+ }
if (proc.anrDialog != null) {
Slog.e(TAG, "App already has anr dialog: " + proc);
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
@@ -851,6 +864,10 @@
if (dialogToShow != null) {
dialogToShow.show();
}
+ // Notify PackageWatchdog without the lock held
+ if (packageList != null) {
+ mPackageWatchdog.onPackageFailure(packageList);
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 65cd329..f9a77af 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -67,8 +67,8 @@
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class);
- sGlobalSettingToTypeMap.put(Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
- String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_IN_APPS, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACK_LIST, String.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 117984e..d133dea 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1362,8 +1362,9 @@
mService.mNativeDebuggingApp = null;
}
- if (app.info.isPrivilegedApp() &&
- DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet())) {
+ if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY) != 0
+ || (app.info.isPrivilegedApp()
+ && DexManager.isPackageSelectedToRunOob(app.pkgList.mPkgList.keySet()))) {
runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
}
@@ -1613,6 +1614,13 @@
app.addPackage(info.packageName, info.versionCode, mService.mProcessStats);
checkSlow(startTime, "startProcess: done, added package to proc");
return app;
+ } else if (app.getActiveInstrumentation() != null) {
+ // We don't want to kill running instrumentation.
+ if (DEBUG_PROCESSES) {
+ Slog.v(TAG_PROCESSES, "Instrumentation already running: " + app);
+ }
+ checkSlow(startTime, "startProcess: keep instrumentation proc");
+ return app;
}
// An application record is attached to a previous process,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6cde4ad..d704a3e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7822,6 +7822,36 @@
return AudioManager.SUCCESS;
}
+ /** see AudioPolicy.setUidDeviceAffinity() */
+ public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
+ @NonNull int[] deviceTypes,
+ @NonNull String[] deviceAddresses) {
+ synchronized (mAudioPolicies) {
+ final AudioPolicyProxy app =
+ checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
+ if (app == null) {
+ return AudioManager.ERROR;
+ }
+ if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
+ return AudioManager.ERROR;
+ }
+ }
+ return AudioManager.SUCCESS;
+ }
+
+ /** see AudioPolicy.removeUidDeviceAffinity() */
+ public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
+ synchronized (mAudioPolicies) {
+ final AudioPolicyProxy app =
+ checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
+ if (app == null) {
+ return AudioManager.ERROR;
+ }
+
+ }
+ return AudioManager.SUCCESS;
+ }
+
public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
+ " policy " + pcb.asBinder());
@@ -7994,6 +8024,15 @@
//======================
// Audio policy proxy
//======================
+ private static final class AudioDeviceArray {
+ final @NonNull int[] mDeviceTypes;
+ final @NonNull String[] mDeviceAddresses;
+ AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
+ mDeviceTypes = types;
+ mDeviceAddresses = addresses;
+ }
+ }
+
/**
* This internal class inherits from AudioPolicyConfig, each instance contains all the
* mixes of an AudioPolicy and their configurations.
@@ -8003,6 +8042,8 @@
final IAudioPolicyCallback mPolicyCallback;
final boolean mHasFocusListener;
final boolean mIsVolumeController;
+ final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
+ new HashMap<Integer, AudioDeviceArray>();
/**
* Audio focus ducking behavior for an audio policy.
* This variable reflects the value that was successfully set in
@@ -8075,6 +8116,26 @@
return false;
}
+ // Verify all the devices in the array are served by mixes defined in this policy
+ boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
+ @NonNull String[] deviceAddresses) {
+ for (int i = 0; i < deviceTypes.length; i++) {
+ boolean hasDevice = false;
+ for (AudioMix mix : mMixes) {
+ // this will check both that the mix has ROUTE_FLAG_RENDER and the device
+ // is reached by this mix
+ if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
+ hasDevice = true;
+ break;
+ }
+ }
+ if (!hasDevice) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void addMixes(@NonNull ArrayList<AudioMix> mixes) {
// TODO optimize to not have to unregister the mixes already in place
synchronized (mMixes) {
@@ -8098,6 +8159,29 @@
AudioSystem.registerPolicyMixes(mMixes, true);
Binder.restoreCallingIdentity(identity);
}
+
+ void setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
+ final Integer Uid = new Integer(uid);
+ if (mUidDeviceAffinities.remove(Uid) != null) {
+ final long identity = Binder.clearCallingIdentity();
+ AudioSystem.removeUidDeviceAffinities(uid);
+ Binder.restoreCallingIdentity(identity);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ final int res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
+ Binder.restoreCallingIdentity(identity);
+ if (res == AudioSystem.SUCCESS) {
+ mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
+ }
+ }
+
+ void removeUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
+ if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
+ final long identity = Binder.clearCallingIdentity();
+ AudioSystem.removeUidDeviceAffinities(uid);
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
};
//======================
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index b6c82d3..73d3d95 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -16,6 +16,7 @@
package com.android.server.display;
+import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
import android.animation.Animator;
@@ -31,6 +32,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.hardware.display.ColorDisplayManager;
import android.hardware.display.IColorDisplayManager;
import android.net.Uri;
import android.opengl.Matrix;
@@ -86,23 +88,94 @@
*/
private static final ColorMatrixEvaluator COLOR_MATRIX_EVALUATOR = new ColorMatrixEvaluator();
+ private final TintController mNightDisplayTintController = new TintController() {
+
+ private float[] mMatrixNightDisplay = new float[16];
+ private final float[] mColorTempCoefficients = new float[9];
+
+ /**
+ * Set coefficients based on whether the color matrix is linear or not.
+ */
+ @Override
+ public void setUp(Context context, boolean needsLinear) {
+ final String[] coefficients = context.getResources().getStringArray(needsLinear
+ ? R.array.config_nightDisplayColorTemperatureCoefficients
+ : R.array.config_nightDisplayColorTemperatureCoefficientsNative);
+ for (int i = 0; i < 9 && i < coefficients.length; i++) {
+ mColorTempCoefficients[i] = Float.parseFloat(coefficients[i]);
+ }
+ }
+
+ @Override
+ public void setMatrix(int cct) {
+ if (mMatrixNightDisplay.length != 16) {
+ Slog.d(TAG, "The display transformation matrix must be 4x4");
+ return;
+ }
+
+ Matrix.setIdentityM(mMatrixNightDisplay, 0);
+
+ final float squareTemperature = cct * cct;
+ final float red = squareTemperature * mColorTempCoefficients[0]
+ + cct * mColorTempCoefficients[1] + mColorTempCoefficients[2];
+ final float green = squareTemperature * mColorTempCoefficients[3]
+ + cct * mColorTempCoefficients[4] + mColorTempCoefficients[5];
+ final float blue = squareTemperature * mColorTempCoefficients[6]
+ + cct * mColorTempCoefficients[7] + mColorTempCoefficients[8];
+ mMatrixNightDisplay[0] = red;
+ mMatrixNightDisplay[5] = green;
+ mMatrixNightDisplay[10] = blue;
+ }
+
+ @Override
+ public float[] getMatrix() {
+ return isActivated() ? mMatrixNightDisplay : MATRIX_IDENTITY;
+ }
+
+ @Override
+ public int getLevel() {
+ return LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
+ }
+ };
+
+ private final TintController mDisplayWhiteBalanceTintController = new TintController() {
+
+ private float[] mMatrixDisplayWhiteBalance = new float[16];
+
+ @Override
+ public void setUp(Context context, boolean needsLinear) {
+ }
+
+ @Override
+ public float[] getMatrix() {
+ return isActivated() ? mMatrixDisplayWhiteBalance : MATRIX_IDENTITY;
+ }
+
+ @Override
+ public void setMatrix(int cct) {
+ }
+
+ @Override
+ public int getLevel() {
+ return LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
+ }
+ };
+
private final Handler mHandler;
- private float[] mMatrixNight = new float[16];
-
- private final float[] mColorTempCoefficients = new float[9];
-
private int mCurrentUser = UserHandle.USER_NULL;
private ContentObserver mUserSetupObserver;
private boolean mBootCompleted;
private ColorDisplayController mNightDisplayController;
private ContentObserver mContentObserver;
- private ValueAnimator mColorMatrixAnimator;
- private Boolean mIsNightDisplayActivated;
+ private DisplayWhiteBalanceListener mDisplayWhiteBalanceListener;
+
private NightDisplayAutoMode mNightDisplayAutoMode;
+ private Integer mDisplayWhiteBalanceColorTemperature;
+
public ColorDisplayService(Context context) {
super(context);
mHandler = new Handler(Looper.getMainLooper());
@@ -111,6 +184,7 @@
@Override
public void onStart() {
publishBinderService(Context.COLOR_DISPLAY_SERVICE, new BinderService());
+ publishLocalService(ColorDisplayServiceInternal.class, new ColorDisplayServiceInternal());
}
@Override
@@ -232,6 +306,9 @@
case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED:
onAccessibilityTransformChanged();
break;
+ case Secure.DISPLAY_WHITE_BALANCE_ENABLED:
+ onDisplayWhiteBalanceEnabled(isDisplayWhiteBalanceSettingEnabled());
+ break;
}
}
}
@@ -256,25 +333,41 @@
cr.registerContentObserver(
Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
// Set the color mode, if valid, and immediately apply the updated tint matrix based on the
// existing activated state. This ensures consistency of tint across the color mode change.
onDisplayColorModeChanged(mNightDisplayController.getColorMode());
- // Reset the activated state.
- mIsNightDisplayActivated = null;
+ if (ColorDisplayManager.isNightDisplayAvailable(getContext())) {
+ // Reset the activated state.
+ mNightDisplayTintController.setActivated(null);
- setCoefficientMatrix(getContext(), DisplayTransformManager.needsLinearColorMatrix());
+ // Prepare the night display color transformation matrix.
+ mNightDisplayTintController
+ .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
+ mNightDisplayTintController.setMatrix(mNightDisplayController.getColorTemperature());
- // Prepare color transformation matrix.
- setMatrix(mNightDisplayController.getColorTemperature(), mMatrixNight);
+ // Initialize the current auto mode.
+ onNightDisplayAutoModeChanged(mNightDisplayController.getAutoMode());
- // Initialize the current auto mode.
- onNightDisplayAutoModeChanged(mNightDisplayController.getAutoMode());
+ // Force the initialization current activated state.
+ if (mNightDisplayTintController.isActivatedStateNotSet()) {
+ onNightDisplayActivated(mNightDisplayController.isActivated());
+ }
+ }
- // Force the initialization current activated state.
- if (mIsNightDisplayActivated == null) {
- onNightDisplayActivated(mNightDisplayController.isActivated());
+ if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) {
+ // Prepare the display white balance transform matrix.
+ mDisplayWhiteBalanceTintController
+ .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
+ if (mDisplayWhiteBalanceColorTemperature != null) {
+ mDisplayWhiteBalanceTintController
+ .setMatrix(mDisplayWhiteBalanceColorTemperature);
+ }
+
+ onDisplayWhiteBalanceEnabled(isDisplayWhiteBalanceSettingEnabled());
}
}
@@ -287,28 +380,31 @@
mNightDisplayController = null;
}
- if (mNightDisplayAutoMode != null) {
- mNightDisplayAutoMode.onStop();
- mNightDisplayAutoMode = null;
+ if (ColorDisplayManager.isNightDisplayAvailable(getContext())) {
+ if (mNightDisplayAutoMode != null) {
+ mNightDisplayAutoMode.onStop();
+ mNightDisplayAutoMode = null;
+ }
+ mNightDisplayTintController.endAnimator();
}
- if (mColorMatrixAnimator != null) {
- mColorMatrixAnimator.end();
- mColorMatrixAnimator = null;
+ if (ColorDisplayManager.isDisplayWhiteBalanceAvailable(getContext())) {
+ mDisplayWhiteBalanceTintController.endAnimator();
}
}
private void onNightDisplayActivated(boolean activated) {
- if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activated) {
+ if (mNightDisplayTintController.isActivatedStateNotSet()
+ || mNightDisplayTintController.isActivated() != activated) {
Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
- mIsNightDisplayActivated = activated;
+ mNightDisplayTintController.setActivated(activated);
if (mNightDisplayAutoMode != null) {
mNightDisplayAutoMode.onActivated(activated);
}
- applyTint(false);
+ applyTint(mNightDisplayTintController, false);
}
}
@@ -348,8 +444,8 @@
}
private void onNightDisplayColorTemperatureChanged(int colorTemperature) {
- setMatrix(colorTemperature, mMatrixNight);
- applyTint(true);
+ mNightDisplayTintController.setMatrix(colorTemperature);
+ applyTint(mNightDisplayTintController, true);
}
private void onDisplayColorModeChanged(int mode) {
@@ -357,66 +453,53 @@
return;
}
- // Cancel the night display tint animator if it's running.
- if (mColorMatrixAnimator != null) {
- mColorMatrixAnimator.cancel();
+ mNightDisplayTintController.cancelAnimator();
+ mDisplayWhiteBalanceTintController.cancelAnimator();
+
+ mNightDisplayTintController
+ .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
+ mNightDisplayTintController.setMatrix(mNightDisplayController.getColorTemperature());
+
+ mDisplayWhiteBalanceTintController
+ .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
+ if (mDisplayWhiteBalanceColorTemperature != null) {
+ mDisplayWhiteBalanceTintController.setMatrix(mDisplayWhiteBalanceColorTemperature);
}
- setCoefficientMatrix(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
- setMatrix(mNightDisplayController.getColorTemperature(), mMatrixNight);
-
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
- dtm.setColorMode(mode, (mIsNightDisplayActivated != null && mIsNightDisplayActivated)
- ? mMatrixNight : MATRIX_IDENTITY);
+ dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
}
private void onAccessibilityTransformChanged() {
onDisplayColorModeChanged(mNightDisplayController.getColorMode());
}
- /**
- * Set coefficients based on whether the color matrix is linear or not.
- */
- private void setCoefficientMatrix(Context context, boolean needsLinear) {
- final String[] coefficients = context.getResources().getStringArray(needsLinear
- ? R.array.config_nightDisplayColorTemperatureCoefficients
- : R.array.config_nightDisplayColorTemperatureCoefficientsNative);
- for (int i = 0; i < 9 && i < coefficients.length; i++) {
- mColorTempCoefficients[i] = Float.parseFloat(coefficients[i]);
- }
- }
/**
* Applies current color temperature matrix, or removes it if deactivated.
*
* @param immediate {@code true} skips transition animation
*/
- private void applyTint(boolean immediate) {
- // Cancel the old animator if still running.
- if (mColorMatrixAnimator != null) {
- mColorMatrixAnimator.cancel();
- }
+ private void applyTint(TintController tintController, boolean immediate) {
+ tintController.cancelAnimator();
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
- final float[] from = dtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY);
- final float[] to = mIsNightDisplayActivated ? mMatrixNight : MATRIX_IDENTITY;
+ final float[] from = dtm.getColorMatrix(tintController.getLevel());
+ final float[] to = tintController.getMatrix();
if (immediate) {
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
+ dtm.setColorMatrix(tintController.getLevel(), to);
} else {
- mColorMatrixAnimator = ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
- from == null ? MATRIX_IDENTITY : from, to);
- mColorMatrixAnimator.setDuration(TRANSITION_DURATION);
- mColorMatrixAnimator.setInterpolator(AnimationUtils.loadInterpolator(
+ tintController.setAnimator(ValueAnimator.ofObject(COLOR_MATRIX_EVALUATOR,
+ from == null ? MATRIX_IDENTITY : from, to));
+ tintController.getAnimator().setDuration(TRANSITION_DURATION);
+ tintController.getAnimator().setInterpolator(AnimationUtils.loadInterpolator(
getContext(), android.R.interpolator.fast_out_slow_in));
- mColorMatrixAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animator) {
- final float[] value = (float[]) animator.getAnimatedValue();
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, value);
- }
+ tintController.getAnimator().addUpdateListener((ValueAnimator animator) -> {
+ final float[] value = (float[]) animator.getAnimatedValue();
+ dtm.setColorMatrix(tintController.getLevel(), value);
});
- mColorMatrixAnimator.addListener(new AnimatorListenerAdapter() {
+ tintController.getAnimator().addListener(new AnimatorListenerAdapter() {
private boolean mIsCancelled;
@@ -431,42 +514,16 @@
// Ensure final color matrix is set at the end of the animation. If the
// animation is cancelled then don't set the final color matrix so the new
// animator can pick up from where this one left off.
- dtm.setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, to);
+ dtm.setColorMatrix(tintController.getLevel(), to);
}
- mColorMatrixAnimator = null;
+ tintController.setAnimator(null);
}
});
- mColorMatrixAnimator.start();
+ tintController.getAnimator().start();
}
}
/**
- * Set the color transformation {@code MATRIX_NIGHT} to the given color temperature.
- *
- * @param colorTemperature color temperature in Kelvin
- * @param outTemp the 4x4 display transformation matrix for that color temperature
- */
- private void setMatrix(int colorTemperature, float[] outTemp) {
- if (outTemp.length != 16) {
- Slog.d(TAG, "The display transformation matrix must be 4x4");
- return;
- }
-
- Matrix.setIdentityM(mMatrixNight, 0);
-
- final float squareTemperature = colorTemperature * colorTemperature;
- final float red = squareTemperature * mColorTempCoefficients[0]
- + colorTemperature * mColorTempCoefficients[1] + mColorTempCoefficients[2];
- final float green = squareTemperature * mColorTempCoefficients[3]
- + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[5];
- final float blue = squareTemperature * mColorTempCoefficients[6]
- + colorTemperature * mColorTempCoefficients[7] + mColorTempCoefficients[8];
- outTemp[0] = red;
- outTemp[5] = green;
- outTemp[10] = blue;
- }
-
- /**
* Returns the first date time corresponding to the local time that occurs before the provided
* date time.
*
@@ -498,6 +555,18 @@
return ldt.isBefore(compareTime) ? ldt.plusDays(1) : ldt;
}
+ private void onDisplayWhiteBalanceEnabled(boolean enabled) {
+ mDisplayWhiteBalanceTintController.setActivated(enabled);
+ if (mDisplayWhiteBalanceListener != null) {
+ mDisplayWhiteBalanceListener.onDisplayWhiteBalanceStatusChanged(enabled);
+ }
+ }
+
+ private boolean isDisplayWhiteBalanceSettingEnabled() {
+ return Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.DISPLAY_WHITE_BALANCE_ENABLED, 0, mCurrentUser) == 1;
+ }
+
private boolean isDeviceColorManagedInternal() {
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
return dtm.isDeviceColorManaged();
@@ -507,7 +576,7 @@
* Returns the last time the night display transform activation state was changed, or {@link
* LocalDateTime#MIN} if night display has never been activated.
*/
- private @NonNull LocalDateTime getNightDisplayLastActivatedTimeSetting() {
+ private LocalDateTime getNightDisplayLastActivatedTimeSetting() {
final ContentResolver cr = getContext().getContentResolver();
final String lastActivatedTime = Secure.getStringForUser(
cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, getContext().getUserId());
@@ -577,11 +646,12 @@
}
}
- if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activate) {
+ if (mNightDisplayTintController.isActivatedStateNotSet() || (
+ mNightDisplayTintController.isActivated() != activate)) {
mNightDisplayController.setActivated(activate);
}
- updateNextAlarm(mIsNightDisplayActivated, now);
+ updateNextAlarm(mNightDisplayTintController.isActivated(), now);
}
private void updateNextAlarm(@Nullable Boolean activated, @NonNull LocalDateTime now) {
@@ -672,7 +742,8 @@
}
}
- if (mIsNightDisplayActivated == null || mIsNightDisplayActivated != activate) {
+ if (mNightDisplayTintController.isActivatedStateNotSet() || (
+ mNightDisplayTintController.isActivated() != activate)) {
mNightDisplayController.setActivated(activate);
}
}
@@ -724,6 +795,115 @@
}
}
+ private abstract static class TintController {
+
+ private ValueAnimator mAnimator;
+ private Boolean mIsActivated;
+
+ public ValueAnimator getAnimator() {
+ return mAnimator;
+ }
+
+ public void setAnimator(ValueAnimator animator) {
+ mAnimator = animator;
+ }
+
+ /**
+ * Cancel the animator if it's still running.
+ */
+ public void cancelAnimator() {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ }
+
+ /**
+ * End the animator if it's still running, jumping to the end state.
+ */
+ public void endAnimator() {
+ if (mAnimator != null) {
+ mAnimator.end();
+ mAnimator = null;
+ }
+ }
+
+ public void setActivated(Boolean isActivated) {
+ mIsActivated = isActivated;
+ }
+
+ public boolean isActivated() {
+ return mIsActivated != null && mIsActivated;
+ }
+
+ public boolean isActivatedStateNotSet() {
+ return mIsActivated == null;
+ }
+
+ /**
+ * Set up any constants needed for computing the matrix.
+ */
+ public abstract void setUp(Context context, boolean needsLinear);
+
+ /**
+ * Sets the 4x4 matrix to apply.
+ */
+ public abstract void setMatrix(int value);
+
+ /**
+ * Get the 4x4 matrix to apply.
+ */
+ public abstract float[] getMatrix();
+
+ /**
+ * Get the color transform level to apply the matrix.
+ */
+ public abstract int getLevel();
+ }
+
+ /**
+ * Local service that allows color transforms to be enabled from other system services.
+ */
+ public final class ColorDisplayServiceInternal {
+
+ /**
+ * Set the current CCT value for the display white balance transform, and if the transform
+ * is enabled, apply it.
+ *
+ * @param cct the color temperature in Kelvin.
+ */
+ public boolean setDisplayWhiteBalanceColorTemperature(int cct) {
+ // Update the transform matrix even if it can't be applied.
+ mDisplayWhiteBalanceColorTemperature = cct;
+ mDisplayWhiteBalanceTintController.setMatrix(cct);
+
+ if (mDisplayWhiteBalanceTintController.isActivated()) {
+ applyTint(mDisplayWhiteBalanceTintController, true);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the listener and returns whether display white balance is currently enabled.
+ */
+ public boolean setDisplayWhiteBalanceListener(DisplayWhiteBalanceListener listener) {
+ mDisplayWhiteBalanceListener = listener;
+ return mDisplayWhiteBalanceTintController.isActivated();
+ }
+ }
+
+ /**
+ * Listener for changes in display white balance status.
+ */
+ public interface DisplayWhiteBalanceListener {
+
+ /**
+ * Notify that the display white balance status has changed, either due to preemption by
+ * another transform or the feature being turned off.
+ */
+ void onDisplayWhiteBalanceStatusChanged(boolean enabled);
+ }
+
private final class BinderService extends IColorDisplayManager.Stub {
@Override
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
index 4ad26da..a5e9728 100644
--- a/services/core/java/com/android/server/display/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -45,6 +45,10 @@
*/
public static final int LEVEL_COLOR_MATRIX_NIGHT_DISPLAY = 100;
/**
+ * Color transform level used by display white balance to adjust the display's white point.
+ */
+ public static final int LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE = 125;
+ /**
* Color transform level used to adjust the color saturation of the display.
*/
public static final int LEVEL_COLOR_MATRIX_SATURATION = 150;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index dd2abde..d49c4a9 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -236,6 +236,7 @@
* {@link AudioManager#ADJUST_SAME}.
*
* @param packageName The package that made the original volume request.
+ * @param opPackageName The op package that made the original volume request.
* @param pid The pid that made the original volume request.
* @param uid The uid that made the original volume request.
* @param caller caller binder. can be {@code null} if it's from the volume key.
@@ -248,7 +249,7 @@
* @param flags Any of the flags from {@link AudioManager}.
* @param useSuggested True to use adjustSuggestedStreamVolume instead of
*/
- public void adjustVolume(String packageName, int pid, int uid,
+ public void adjustVolume(String packageName, String opPackageName, int pid, int uid,
ControllerCallbackLink caller, boolean asSystemService, int direction, int flags,
boolean useSuggested) {
int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND;
@@ -258,8 +259,8 @@
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
// Adjust the volume with a handler not to be blocked by other system service.
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
- postAdjustLocalVolume(stream, direction, flags, packageName, uid, asSystemService,
- useSuggested, previousFlagPlaySound);
+ postAdjustLocalVolume(stream, direction, flags, opPackageName, pid, uid,
+ asSystemService, useSuggested, previousFlagPlaySound);
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
// Nothing to do, the volume cannot be changed
@@ -290,11 +291,23 @@
}
}
- private void setVolumeTo(String packageName, int pid, int uid,
+ private void setVolumeTo(String packageName, String opPackageName, int pid, int uid,
ControllerCallbackLink caller, int value, int flags) {
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
- mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
+ final int volumeValue = value;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mAudioManagerInternal.setStreamVolumeForUid(stream, volumeValue, flags,
+ opPackageName, uid);
+ } catch (IllegalArgumentException | SecurityException e) {
+ Log.e(TAG, "Cannot set volume: stream=" + stream + ", value=" + volumeValue
+ + ", flags=" + flags, e);
+ }
+ }
+ });
} else {
if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
// Nothing to do. The volume can't be set directly.
@@ -465,11 +478,19 @@
}
private void postAdjustLocalVolume(final int stream, final int direction, final int flags,
- final String callingPackageName, final int callingUid, final boolean asSystemService,
- final boolean useSuggested, final int previousFlagPlaySound) {
- final String packageName = asSystemService
- ? mContext.getOpPackageName() : callingPackageName;
- final int uid = asSystemService ? Process.SYSTEM_UID : callingUid;
+ final String callingOpPackageName, final int callingPid, final int callingUid,
+ final boolean asSystemService, final boolean useSuggested,
+ final int previousFlagPlaySound) {
+ // Must use opPackageName for adjusting volumes with UID.
+ final String opPackageName;
+ final int uid;
+ if (asSystemService) {
+ opPackageName = mContext.getOpPackageName();
+ uid = Process.SYSTEM_UID;
+ } else {
+ opPackageName = callingOpPackageName;
+ uid = callingUid;
+ }
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -477,19 +498,19 @@
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream,
- direction, flags, packageName, uid);
+ direction, flags, opPackageName, uid);
} else {
mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(
AudioManager.USE_DEFAULT_STREAM_TYPE, direction,
- flags | previousFlagPlaySound, packageName, uid);
+ flags | previousFlagPlaySound, opPackageName, uid);
}
} else {
mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
- packageName, uid);
+ opPackageName, uid);
}
} catch (IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream="
- + stream + ", flags=" + flags + ", packageName=" + packageName
+ + stream + ", flags=" + flags + ", opPackageName=" + opPackageName
+ ", uid=" + uid + ", useSuggested=" + useSuggested
+ ", previousFlagPlaySound=" + previousFlagPlaySound, e);
}
@@ -1256,27 +1277,28 @@
}
@Override
- public void adjustVolume(String packageName, ControllerCallbackLink caller,
- boolean asSystemService, int direction, int flags) {
+ public void adjustVolume(String packageName, String opPackageName,
+ ControllerCallbackLink caller, boolean asSystemService, int direction, int flags) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.adjustVolume(packageName, pid, uid, caller, asSystemService,
- direction, flags, false /* useSuggested */);
+ MediaSessionRecord.this.adjustVolume(packageName, opPackageName, pid, uid, caller,
+ asSystemService, direction, flags, false /* useSuggested */);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override
- public void setVolumeTo(String packageName, ControllerCallbackLink caller,
- int value, int flags) {
+ public void setVolumeTo(String packageName, String opPackageName,
+ ControllerCallbackLink caller, int value, int flags) {
int pid = Binder.getCallingPid();
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, caller, value, flags);
+ MediaSessionRecord.this.setVolumeTo(packageName, opPackageName, pid, uid, caller,
+ value, flags);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b807c47..7dbabda 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -35,6 +35,7 @@
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.media.AudioManager;
+import android.media.AudioManagerInternal;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
import android.media.IAudioService;
@@ -72,6 +73,7 @@
import android.view.ViewConfiguration;
import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
@@ -108,6 +110,8 @@
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
+ private AudioManagerInternal mAudioManagerInternal;
+ private ActivityManager mActivityManager;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
private boolean mHasFeatureLeanback;
@@ -139,6 +143,9 @@
mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
+ mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
+ mActivityManager =
+ (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance();
mAudioPlayerStateMonitor.registerListener(
(config, isRemoved) -> {
@@ -1202,7 +1209,8 @@
* there's no active global priority session, long-pressess will be sent to the
* long-press listener instead of adjusting volume.
*
- * @param packageName The caller package.
+ * @param packageName The caller's package name, obtained by Context#getPackageName()
+ * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
* @param asSystemService {@code true} if the event sent to the session as if it was come
* from the system service instead of the app process. This helps sessions to
* distinguish between the key injection by the app and key events from the
@@ -1217,8 +1225,8 @@
* @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
*/
@Override
- public void dispatchVolumeKeyEvent(String packageName, boolean asSystemService,
- KeyEvent keyEvent, int stream, boolean musicOnly) {
+ public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
+ boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
if (keyEvent == null ||
(keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
&& keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
@@ -1240,8 +1248,8 @@
synchronized (mLock) {
if (isGlobalPriorityActiveLocked()
|| mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
- dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
- keyEvent, stream, musicOnly);
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService, keyEvent, stream, musicOnly);
} else {
// TODO: Consider the case when both volume up and down keys are pressed
// at the same time.
@@ -1274,12 +1282,13 @@
&& mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
.getDownTime() == keyEvent.getDownTime()) {
// Short-press. Should change volume.
- dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService,
mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
mCurrentFullUserRecord.mInitialDownVolumeStream,
mCurrentFullUserRecord.mInitialDownMusicOnly);
- dispatchVolumeKeyEventLocked(packageName, pid, uid, asSystemService,
- keyEvent, stream, musicOnly);
+ dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+ asSystemService, keyEvent, stream, musicOnly);
} else {
dispatchVolumeKeyLongPressLocked(keyEvent);
}
@@ -1291,8 +1300,9 @@
}
}
- private void dispatchVolumeKeyEventLocked(String packageName, int pid, int uid,
- boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
+ private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid,
+ int uid, boolean asSystemService, KeyEvent keyEvent, int stream,
+ boolean musicOnly) {
boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
int direction = 0;
@@ -1326,26 +1336,26 @@
if (up) {
direction = 0;
}
- dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream,
- direction, flags);
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+ asSystemService, stream, direction, flags);
} else if (isMute) {
if (down && keyEvent.getRepeatCount() == 0) {
- dispatchAdjustVolumeLocked(packageName, pid, uid, asSystemService, stream,
- AudioManager.ADJUST_TOGGLE_MUTE, flags);
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+ asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
}
}
}
}
@Override
- public void dispatchAdjustVolume(String packageName, int suggestedStream, int delta,
- int flags) {
+ public void dispatchAdjustVolume(String packageName, String opPackageName,
+ int suggestedStream, int delta, int flags) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- dispatchAdjustVolumeLocked(packageName, pid, uid, false,
+ dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false,
suggestedStream, delta, flags);
}
} finally {
@@ -1409,24 +1419,14 @@
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- int controllerUserId = UserHandle.getUserId(controllerUid);
- int controllerUidFromPackageName;
- try {
- controllerUidFromPackageName = getContext().getPackageManager()
- .getPackageUidAsUser(controllerPackageName, controllerUserId);
- } catch (NameNotFoundException e) {
- if (DEBUG) {
- Log.d(TAG, "Package " + controllerPackageName + " doesn't exist");
- }
- return false;
- }
- if (controllerUidFromPackageName != controllerUid) {
- if (DEBUG) {
- Log.d(TAG, "Package name " + controllerPackageName
- + " doesn't match with the uid " + controllerUid);
- }
- return false;
- }
+ // Don't perform sanity check between controllerPackageName and controllerUid.
+ // When an (activity|service) runs on the another apps process by specifying
+ // android:process in the AndroidManifest.xml, then PID and UID would have the
+ // running process' information instead of the (activity|service) that has created
+ // MediaController.
+ // Note that we can use Context#getOpPackageName() instead of
+ // Context#getPackageName() for getting package name that matches with the PID/UID,
+ // but it doesn't tell which package has created the MediaController, so useless.
return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
controllerPid, controllerUid);
} finally {
@@ -1497,8 +1497,8 @@
return false;
}
- private void dispatchAdjustVolumeLocked(String packageName, int pid, int uid,
- boolean asSystemService, int suggestedStream, int direction, int flags) {
+ private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
+ int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
: mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
@@ -1529,21 +1529,28 @@
mHandler.post(new Runnable() {
@Override
public void run() {
+ final String callingOpPackageName;
+ final int callingUid;
+ if (asSystemService) {
+ callingOpPackageName = getContext().getOpPackageName();
+ callingUid = Process.myUid();
+ } else {
+ callingOpPackageName = opPackageName;
+ callingUid = uid;
+ }
try {
- String packageName = getContext().getOpPackageName();
- mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
- flags, packageName, TAG);
- } catch (RemoteException|SecurityException e) {
- Log.e(TAG, "Error adjusting default volume.", e);
- } catch (IllegalArgumentException e) {
+ mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
+ direction, flags, callingOpPackageName, callingUid);
+ } catch (SecurityException | IllegalArgumentException e) {
Log.e(TAG, "Cannot adjust volume: direction=" + direction
- + ", suggestedStream=" + suggestedStream + ", flags=" + flags,
- e);
+ + ", suggestedStream=" + suggestedStream + ", flags=" + flags
+ + ", packageName=" + packageName + ", uid=" + uid
+ + ", asSystemService=" + asSystemService, e);
}
}
});
} else {
- session.adjustVolume(packageName, pid, uid, null, asSystemService,
+ session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
direction, flags, true);
}
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 6187583..88d73fb 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -558,7 +558,7 @@
if (pkgList != null && (pkgList.length > 0)) {
boolean anyServicesInvolved = false;
// Remove notification settings for uninstalled package
- if (removingPackage) {
+ if (removingPackage && uidList != null) {
int size = Math.min(pkgList.length, uidList.length);
for (int i = 0; i < size; i++) {
final String pkg = pkgList[i];
@@ -570,9 +570,11 @@
if (mEnabledServicesPackageNames.contains(pkgName)) {
anyServicesInvolved = true;
}
- for (int uid : uidList) {
- if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
- anyServicesInvolved = true;
+ if (uidList != null && uidList.length > 0) {
+ for (int uid : uidList) {
+ if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
+ anyServicesInvolved = true;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d961bad..85a8d93 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -144,7 +144,6 @@
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
-import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -3852,7 +3851,8 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
- new ShellCmd().exec(this, in, out, err, args, callback, resultReceiver);
+ new NotificationShellCmd(NotificationManagerService.this)
+ .exec(this, in, out, err, args, callback, resultReceiver);
}
};
@@ -5258,22 +5258,25 @@
}
if (DBG) Slog.v(TAG, "Interrupting!");
if (hasValidSound) {
- mSoundNotificationKey = key;
if (mInCall) {
playInCallNotification();
beep = true;
} else {
beep = playSound(record, soundUri);
}
+ if(beep) {
+ mSoundNotificationKey = key;
+ }
}
final boolean ringerModeSilent =
mAudioManager.getRingerModeInternal()
== AudioManager.RINGER_MODE_SILENT;
if (!mInCall && hasValidVibrate && !ringerModeSilent) {
- mVibrateNotificationKey = key;
-
buzz = playVibration(record, vibration, hasValidSound);
+ if(buzz) {
+ mVibrateNotificationKey = key;
+ }
}
} else if ((record.getFlags() & Notification.FLAG_INSISTENT) != 0) {
hasValidSound = false;
@@ -5454,8 +5457,17 @@
try {
Thread.sleep(waitMs);
} catch (InterruptedException e) { }
- mVibrator.vibrate(record.sbn.getUid(), record.sbn.getPackageName(),
- effect, "Notification (delayed)", record.getAudioAttributes());
+
+ // Notifications might be canceled before it actually vibrates due to waitMs,
+ // so need to check the notification still valide for vibrate.
+ synchronized (mNotificationLock) {
+ if (mNotificationsByKey.get(record.getKey()) != null) {
+ mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+ effect, "Notification (delayed)", record.getAudioAttributes());
+ } else {
+ Slog.e(TAG, "No vibration for canceled notification : " + record.getKey());
+ }
+ }
}).start();
} else {
mVibrator.vibrate(record.sbn.getUid(), record.sbn.getPackageName(),
@@ -7715,110 +7727,6 @@
}
}
- private class ShellCmd extends ShellCommand {
- public static final String USAGE = "help\n"
- + "allow_listener COMPONENT [user_id]\n"
- + "disallow_listener COMPONENT [user_id]\n"
- + "allow_assistant COMPONENT\n"
- + "remove_assistant COMPONENT\n"
- + "allow_dnd PACKAGE\n"
- + "disallow_dnd PACKAGE\n"
- + "suspend_package PACKAGE\n"
- + "unsuspend_package PACKAGE";
-
- @Override
- public int onCommand(String cmd) {
- if (cmd == null) {
- return handleDefaultCommands(cmd);
- }
- final PrintWriter pw = getOutPrintWriter();
- try {
- switch (cmd) {
- case "allow_dnd": {
- getBinderService().setNotificationPolicyAccessGranted(
- getNextArgRequired(), true);
- }
- break;
-
- case "disallow_dnd": {
- getBinderService().setNotificationPolicyAccessGranted(
- getNextArgRequired(), false);
- }
- break;
- case "allow_listener": {
- ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
- if (cn == null) {
- pw.println("Invalid listener - must be a ComponentName");
- return -1;
- }
- String userId = getNextArg();
- if (userId == null) {
- getBinderService().setNotificationListenerAccessGranted(cn, true);
- } else {
- getBinderService().setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), true);
- }
- }
- break;
- case "disallow_listener": {
- ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
- if (cn == null) {
- pw.println("Invalid listener - must be a ComponentName");
- return -1;
- }
- String userId = getNextArg();
- if (userId == null) {
- getBinderService().setNotificationListenerAccessGranted(cn, false);
- } else {
- getBinderService().setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), false);
- }
- }
- break;
- case "allow_assistant": {
- ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
- if (cn == null) {
- pw.println("Invalid assistant - must be a ComponentName");
- return -1;
- }
- getBinderService().setNotificationAssistantAccessGranted(cn, true);
- }
- break;
- case "disallow_assistant": {
- ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
- if (cn == null) {
- pw.println("Invalid assistant - must be a ComponentName");
- return -1;
- }
- getBinderService().setNotificationAssistantAccessGranted(cn, false);
- }
- break;
- case "suspend_package": {
- // only use for testing
- simulatePackageSuspendBroadcast(true, getNextArgRequired());
- }
- break;
- case "unsuspend_package": {
- // only use for testing
- simulatePackageSuspendBroadcast(false, getNextArgRequired());
- }
- break;
- default:
- return handleDefaultCommands(cmd);
- }
- } catch (Exception e) {
- pw.println("Error occurred. Check logcat for details. " + e.getMessage());
- Slog.e(TAG, "Error running shell command", e);
- }
- return 0;
- }
-
- @Override
- public void onHelp() {
- getOutPrintWriter().println(USAGE);
- }
- }
-
private void writeSecureNotificationsPolicy(XmlSerializer out) throws IOException {
out.startTag(null, LOCKSCREEN_ALLOW_SECURE_NOTIFICATIONS_TAG);
out.attribute(null, LOCKSCREEN_ALLOW_SECURE_NOTIFICATIONS_VALUE,
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
new file mode 100644
index 0000000..3d88f20
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -0,0 +1,483 @@
+/*
+ * 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.notification;
+
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Person;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
+import android.content.res.Resources;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.net.URISyntaxException;
+import java.util.Collections;
+
+/**
+ * Implementation of `cmd notification` in NotificationManagerService.
+ */
+public class NotificationShellCmd extends ShellCommand {
+ private static final String USAGE =
+ "usage: cmd notification SUBCMD [args]\n\n"
+ + "SUBCMDs:\n"
+ + " allow_listener COMPONENT [user_id]\n"
+ + " disallow_listener COMPONENT [user_id]\n"
+ + " allow_assistant COMPONENT\n"
+ + " remove_assistant COMPONENT\n"
+ + " allow_dnd PACKAGE\n"
+ + " disallow_dnd PACKAGE\n"
+ + " suspend_package PACKAGE\n"
+ + " unsuspend_package PACKAGE\n"
+ + " post [--help | flags] TAG TEXT";
+
+ private static final String NOTIFY_USAGE =
+ "usage: cmd notification post [flags] <tag> <text>\n\n"
+ + "flags:\n"
+ + " -h|--help\n"
+ + " -v|--verbose\n"
+ + " -t|--title <text>\n"
+ + " -i|--icon <iconspec>\n"
+ + " -I|--large-icon <iconspec>\n"
+ + " -S|--style <style> [styleargs]\n"
+ + " -c|--content-intent <intentspec>\n"
+ + "\n"
+ + "styles: (default none)\n"
+ + " bigtext\n"
+ + " bigpicture --picture <iconspec>\n"
+ + " inbox --line <text> --line <text> ...\n"
+ + " messaging --conversation <title> --message <who>:<text> ...\n"
+ + " media\n"
+ + "\n"
+ + "an <iconspec> is one of\n"
+ + " file:///data/local/tmp/<img.png>\n"
+ + " content://<provider>/<path>\n"
+ + " @[<package>:]drawable/<img>\n"
+ + " data:base64,<B64DATA==>\n"
+ + "\n"
+ + "an <intentspec> is (broadcast|service|activity) <args>\n"
+ + " <args> are as described in `am start`";
+
+ public static final int NOTIFICATION_ID = 1138;
+ public static final String NOTIFICATION_PACKAGE = "com.android.shell";
+ public static final String CHANNEL_ID = "shellcmd";
+ public static final String CHANNEL_NAME = "Shell command";
+ public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_DEFAULT;
+
+ private final NotificationManagerService mDirectService;
+ private final INotificationManager mBinderService;
+
+ public NotificationShellCmd(NotificationManagerService service) {
+ mDirectService = service;
+ mBinderService = service.getBinderService();
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ switch (cmd.replace('-', '_')) {
+ case "allow_dnd": {
+ mBinderService.setNotificationPolicyAccessGranted(
+ getNextArgRequired(), true);
+ }
+ break;
+
+ case "disallow_dnd": {
+ mBinderService.setNotificationPolicyAccessGranted(
+ getNextArgRequired(), false);
+ }
+ break;
+ case "allow_listener": {
+ ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+ if (cn == null) {
+ pw.println("Invalid listener - must be a ComponentName");
+ return -1;
+ }
+ String userId = getNextArg();
+ if (userId == null) {
+ mBinderService.setNotificationListenerAccessGranted(cn, true);
+ } else {
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ cn, Integer.parseInt(userId), true);
+ }
+ }
+ break;
+ case "disallow_listener": {
+ ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+ if (cn == null) {
+ pw.println("Invalid listener - must be a ComponentName");
+ return -1;
+ }
+ String userId = getNextArg();
+ if (userId == null) {
+ mBinderService.setNotificationListenerAccessGranted(cn, false);
+ } else {
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ cn, Integer.parseInt(userId), false);
+ }
+ }
+ break;
+ case "allow_assistant": {
+ ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+ if (cn == null) {
+ pw.println("Invalid assistant - must be a ComponentName");
+ return -1;
+ }
+ mBinderService.setNotificationAssistantAccessGranted(cn, true);
+ }
+ break;
+ case "disallow_assistant": {
+ ComponentName cn = ComponentName.unflattenFromString(getNextArgRequired());
+ if (cn == null) {
+ pw.println("Invalid assistant - must be a ComponentName");
+ return -1;
+ }
+ mBinderService.setNotificationAssistantAccessGranted(cn, false);
+ }
+ break;
+ case "suspend_package": {
+ // only use for testing
+ mDirectService.simulatePackageSuspendBroadcast(true, getNextArgRequired());
+ }
+ break;
+ case "unsuspend_package": {
+ // only use for testing
+ mDirectService.simulatePackageSuspendBroadcast(false, getNextArgRequired());
+ }
+ break;
+ case "post":
+ case "notify":
+ doNotify(pw);
+ break;
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (Exception e) {
+ pw.println("Error occurred. Check logcat for details. " + e.getMessage());
+ Slog.e(NotificationManagerService.TAG, "Error running shell command", e);
+ }
+ return 0;
+ }
+
+ void ensureChannel() throws RemoteException {
+ final int uid = Binder.getCallingUid();
+ final int userid = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (mBinderService.getNotificationChannelForPackage(NOTIFICATION_PACKAGE,
+ uid, CHANNEL_ID, false) == null) {
+ final NotificationChannel chan = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
+ CHANNEL_IMP);
+ Slog.v(NotificationManagerService.TAG,
+ "creating shell channel for user " + userid + " uid " + uid + ": " + chan);
+ mBinderService.createNotificationChannelsForPackage(NOTIFICATION_PACKAGE, uid,
+ new ParceledListSlice<NotificationChannel>(
+ Collections.singletonList(chan)));
+ Slog.v(NotificationManagerService.TAG, "created channel: "
+ + mBinderService.getNotificationChannelForPackage(NOTIFICATION_PACKAGE,
+ uid, CHANNEL_ID, false));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ Icon parseIcon(Resources res, String encoded) throws IllegalArgumentException {
+ if (TextUtils.isEmpty(encoded)) return null;
+ if (encoded.startsWith("/")) {
+ encoded = "file://" + encoded;
+ }
+ if (encoded.startsWith("http:")
+ || encoded.startsWith("https:")
+ || encoded.startsWith("content:")
+ || encoded.startsWith("file:")
+ || encoded.startsWith("android.resource:")) {
+ Uri asUri = Uri.parse(encoded);
+ return Icon.createWithContentUri(asUri);
+ } else if (encoded.startsWith("@")) {
+ final int resid = res.getIdentifier(encoded.substring(1),
+ "drawable", "android");
+ if (resid != 0) {
+ return Icon.createWithResource(res, resid);
+ }
+ } else if (encoded.startsWith("data:")) {
+ encoded = encoded.substring(encoded.indexOf(',') + 1);
+ byte[] bits = android.util.Base64.decode(encoded, android.util.Base64.DEFAULT);
+ return Icon.createWithData(bits, 0, bits.length);
+ }
+ return null;
+ }
+
+ private int doNotify(PrintWriter pw) throws RemoteException, URISyntaxException {
+ final Context context = mDirectService.getContext();
+ final Resources res = context.getResources();
+ final Notification.Builder builder = new Notification.Builder(context, CHANNEL_ID);
+ String opt;
+
+ boolean verbose = false;
+ Notification.BigPictureStyle bigPictureStyle = null;
+ Notification.BigTextStyle bigTextStyle = null;
+ Notification.InboxStyle inboxStyle = null;
+ Notification.MediaStyle mediaStyle = null;
+ Notification.MessagingStyle messagingStyle = null;
+
+ Icon smallIcon = null;
+ while ((opt = getNextOption()) != null) {
+ boolean large = false;
+ switch (opt) {
+ case "-v":
+ case "--verbose":
+ verbose = true;
+ break;
+ case "-t":
+ case "--title":
+ case "title":
+ builder.setContentTitle(getNextArgRequired());
+ break;
+ case "-I":
+ case "--large-icon":
+ case "--largeicon":
+ case "largeicon":
+ case "large-icon":
+ large = true;
+ // fall through
+ case "-i":
+ case "--icon":
+ case "icon":
+ final String iconSpec = getNextArgRequired();
+ final Icon icon = parseIcon(res, iconSpec);
+ if (icon == null) {
+ pw.println("error: invalid icon: " + iconSpec);
+ return -1;
+ }
+ if (large) {
+ builder.setLargeIcon(icon);
+ large = false;
+ } else {
+ smallIcon = icon;
+ }
+ break;
+ case "-c":
+ case "--content-intent":
+ case "content-intent":
+ case "--intent":
+ case "intent":
+ String intentKind = null;
+ switch (peekNextArg()) {
+ case "broadcast":
+ case "service":
+ case "activity":
+ intentKind = getNextArg();
+ }
+ final Intent intent = Intent.parseCommandArgs(this, null);
+ if (intent.getData() == null) {
+ // force unique intents unless you know what you're doing
+ intent.setData(Uri.parse("xyz:" + System.currentTimeMillis()));
+ }
+ final PendingIntent pi;
+ if ("broadcast".equals(intentKind)) {
+ pi = PendingIntent.getBroadcastAsUser(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT,
+ UserHandle.CURRENT);
+ } else if ("service".equals(intentKind)) {
+ pi = PendingIntent.getService(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ } else {
+ pi = PendingIntent.getActivityAsUser(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, null,
+ UserHandle.CURRENT);
+ }
+ builder.setContentIntent(pi);
+ break;
+ case "-S":
+ case "--style":
+ final String styleSpec = getNextArgRequired().toLowerCase();
+ switch (styleSpec) {
+ case "bigtext":
+ bigTextStyle = new Notification.BigTextStyle();
+ builder.setStyle(bigTextStyle);
+ break;
+ case "bigpicture":
+ bigPictureStyle = new Notification.BigPictureStyle();
+ builder.setStyle(bigPictureStyle);
+ break;
+ case "inbox":
+ inboxStyle = new Notification.InboxStyle();
+ builder.setStyle(inboxStyle);
+ break;
+ case "messaging":
+ String name = "You";
+ if ("--user".equals(peekNextArg())) {
+ getNextArg();
+ name = getNextArgRequired();
+ }
+ messagingStyle = new Notification.MessagingStyle(
+ new Person.Builder().setName(name).build());
+ builder.setStyle(messagingStyle);
+ break;
+ case "media":
+ mediaStyle = new Notification.MediaStyle();
+ builder.setStyle(mediaStyle);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "unrecognized notification style: " + styleSpec);
+ }
+ break;
+ case "--bigText": case "--bigtext": case "--big-text":
+ if (bigTextStyle == null) {
+ throw new IllegalArgumentException("--bigtext requires --style bigtext");
+ }
+ bigTextStyle.bigText(getNextArgRequired());
+ break;
+ case "--picture":
+ if (bigPictureStyle == null) {
+ throw new IllegalArgumentException("--picture requires --style bigpicture");
+ }
+ final String pictureSpec = getNextArgRequired();
+ final Icon pictureAsIcon = parseIcon(res, pictureSpec);
+ if (pictureAsIcon == null) {
+ throw new IllegalArgumentException("bad picture spec: " + pictureSpec);
+ }
+ final Drawable d = pictureAsIcon.loadDrawable(context);
+ if (d instanceof BitmapDrawable) {
+ bigPictureStyle.bigPicture(((BitmapDrawable) d).getBitmap());
+ } else {
+ throw new IllegalArgumentException("not a bitmap: " + pictureSpec);
+ }
+ break;
+ case "--line":
+ if (inboxStyle == null) {
+ throw new IllegalArgumentException("--line requires --style inbox");
+ }
+ inboxStyle.addLine(getNextArgRequired());
+ break;
+ case "--message":
+ if (messagingStyle == null) {
+ throw new IllegalArgumentException(
+ "--message requires --style messaging");
+ }
+ String arg = getNextArgRequired();
+ String[] parts = arg.split(":", 2);
+ if (parts.length > 1) {
+ messagingStyle.addMessage(parts[1], System.currentTimeMillis(),
+ parts[0]);
+ } else {
+ messagingStyle.addMessage(parts[0], System.currentTimeMillis(),
+ new String[]{
+ messagingStyle.getUserDisplayName().toString(),
+ "Them"
+ }[messagingStyle.getMessages().size() % 2]);
+ }
+ break;
+ case "--conversation":
+ if (messagingStyle == null) {
+ throw new IllegalArgumentException(
+ "--conversation requires --style messaging");
+ }
+ messagingStyle.setConversationTitle(getNextArgRequired());
+ break;
+ case "-h":
+ case "--help":
+ case "--wtf":
+ default:
+ pw.println(NOTIFY_USAGE);
+ return 0;
+ }
+ }
+
+ final String tag = getNextArg();
+ final String text = getNextArg();
+ if (tag == null || text == null) {
+ pw.println(NOTIFY_USAGE);
+ return -1;
+ }
+
+ builder.setContentText(text);
+
+ if (smallIcon == null) {
+ // uh oh, let's substitute something
+ builder.setSmallIcon(com.android.internal.R.drawable.stat_notify_chat);
+ } else {
+ builder.setSmallIcon(smallIcon);
+ }
+
+ ensureChannel();
+
+ final Notification n = builder.build();
+ pw.println("posting:\n " + n);
+ Slog.v("NotificationManager", "posting: " + n);
+
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mBinderService.enqueueNotificationWithTag(
+ NOTIFICATION_PACKAGE, "android",
+ tag, NOTIFICATION_ID,
+ n, userId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ if (verbose) {
+ NotificationRecord nr = mDirectService.findNotificationLocked(
+ NOTIFICATION_PACKAGE, tag, NOTIFICATION_ID, userId);
+ for (int tries = 3; tries-- > 0; ) {
+ if (nr != null) break;
+ try {
+ pw.println("waiting for notification to post...");
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+ nr = mDirectService.findNotificationLocked(
+ NOTIFICATION_PACKAGE, tag, NOTIFICATION_ID, userId);
+ }
+ if (nr == null) {
+ pw.println("warning: couldn't find notification after enqueueing");
+ } else {
+ pw.println("posted: ");
+ nr.dump(pw, " ", context, false);
+ }
+ }
+
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ getOutPrintWriter().println(USAGE);
+ }
+}
+
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index ee06746..2b4ec03 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -179,13 +179,19 @@
List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
final int userId) {
+ // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // ignored in OverlayManagerService.
return selectWhereTarget(targetPackageName, userId)
+ .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.toList());
}
ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
+ // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+ // ignored in OverlayManagerService.
return selectWhereUser(userId)
+ .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
Collectors.toList()));
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 886cfb2..642bfa2 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -24,8 +24,8 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
@@ -91,7 +91,7 @@
final PackageInfo pi;
try {
pi = mPackageManager.getPackageInfo(packageName,
- PackageManager.GET_META_DATA, Process.SYSTEM_UID);
+ PackageManager.GET_META_DATA, UserHandle.USER_SYSTEM);
Context packageContext = mContext.createPackageContext(packageName, 0);
packageResources = packageContext.getResources();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d4ee61b..d290f3f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -105,6 +105,7 @@
import com.android.server.LocalServices;
import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
+import com.android.server.pm.dex.DexManager;
import libcore.io.IoUtils;
@@ -1594,6 +1595,16 @@
}
}
}
+ if (baseApk.preferCodeIntegrity) {
+ for (File file : mResolvedStagedFiles) {
+ if (file.getName().endsWith(".apk")
+ && !DexManager.auditUncompressedCodeInApk(file.getPath())) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Some code are not uncompressed and aligned correctly for "
+ + mPackageName);
+ }
+ }
+ }
if (baseApk.isSplitRequired && stagedSplits.size() <= 1) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SPLIT,
"Missing split for " + mPackageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index da59b3e..136c7c9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -296,6 +296,7 @@
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
+import com.android.server.PackageWatchdog;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.SystemServerInitThreadPool;
@@ -9492,6 +9493,7 @@
mPackageUsage.writeNow(mPackages);
mCompilerStats.writeNow();
mDexManager.writePackageDexUsageNow();
+ PackageWatchdog.getInstance(mContext).writeNow();
// This is the last chance to write out pending restriction settings
synchronized (mPackages) {
@@ -13021,20 +13023,26 @@
}
@Override
- public boolean canSuspendPackageForUser(String packageName, int userId) {
+ public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
- "canSuspendPackageForUser");
+ "getUnsuspendablePackagesForUser");
final int callingUid = Binder.getCallingUid();
if (UserHandle.getUserId(callingUid) != userId) {
throw new SecurityException("Calling uid " + callingUid
- + " cannot query canSuspendPackageForUser for user " + userId);
+ + " cannot query getUnsuspendablePackagesForUser for user " + userId);
}
+ final ArraySet<String> unactionablePackages = new ArraySet<>();
final long identity = Binder.clearCallingIdentity();
try {
- return canSuspendPackageForUserInternal(packageName, userId);
+ for (String packageName : packageNames) {
+ if (!canSuspendPackageForUserInternal(packageName, userId)) {
+ unactionablePackages.add(packageName);
+ }
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
+ return unactionablePackages.toArray(new String[unactionablePackages.size()]);
}
private boolean canSuspendPackageForUserInternal(String packageName, int userId) {
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 25ef767..e57d9d7 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -785,10 +785,10 @@
* files that can be direclty mapped.
*/
private static void logIfPackageHasUncompressedCode(PackageParser.Package pkg) {
- logIfApkHasUncompressedCode(pkg.baseCodePath);
+ auditUncompressedCodeInApk(pkg.baseCodePath);
if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
for (int i = 0; i < pkg.splitCodePaths.length; i++) {
- logIfApkHasUncompressedCode(pkg.splitCodePaths[i]);
+ auditUncompressedCodeInApk(pkg.splitCodePaths[i]);
}
}
}
@@ -797,34 +797,41 @@
* Generates log if the archive located at {@code fileName} has uncompressed dex file and so
* files that can be direclty mapped.
*/
- private static void logIfApkHasUncompressedCode(String fileName) {
+ public static boolean auditUncompressedCodeInApk(String fileName) {
StrictJarFile jarFile = null;
try {
jarFile = new StrictJarFile(fileName,
false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/);
Iterator<ZipEntry> it = jarFile.iterator();
+ boolean allCorrect = true;
while (it.hasNext()) {
ZipEntry entry = it.next();
if (entry.getName().endsWith(".dex")) {
if (entry.getMethod() != ZipEntry.STORED) {
+ allCorrect = false;
Slog.w(TAG, "APK " + fileName + " has compressed dex code " +
entry.getName());
} else if ((entry.getDataOffset() & 0x3) != 0) {
+ allCorrect = false;
Slog.w(TAG, "APK " + fileName + " has unaligned dex code " +
entry.getName());
}
} else if (entry.getName().endsWith(".so")) {
if (entry.getMethod() != ZipEntry.STORED) {
+ allCorrect = false;
Slog.w(TAG, "APK " + fileName + " has compressed native code " +
entry.getName());
} else if ((entry.getDataOffset() & (0x1000 - 1)) != 0) {
+ allCorrect = false;
Slog.w(TAG, "APK " + fileName + " has unaligned native code " +
entry.getName());
}
}
}
+ return allCorrect;
} catch (IOException ignore) {
Slog.wtf(TAG, "Error when parsing APK " + fileName);
+ return false;
} finally {
try {
if (jarFile != null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f370edf..c792863 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -844,7 +844,7 @@
}
private void interceptBackKeyDown() {
- MetricsLogger.count(mContext, "key_back_down", 1);
+ mLogger.count("key_back_down", 1);
// Reset back key state for long press
mBackKeyHandled = false;
@@ -858,6 +858,7 @@
// returns true if the key was handled and should not be passed to the user
private boolean interceptBackKeyUp(KeyEvent event) {
+ mLogger.count("key_back_up", 1);
// Cache handled state
boolean handled = mBackKeyHandled;
diff --git a/services/core/java/com/android/server/slice/SliceClientPermissions.java b/services/core/java/com/android/server/slice/SliceClientPermissions.java
index e461e0d..ab94a59 100644
--- a/services/core/java/com/android/server/slice/SliceClientPermissions.java
+++ b/services/core/java/com/android/server/slice/SliceClientPermissions.java
@@ -282,9 +282,12 @@
public synchronized void writeTo(XmlSerializer out) throws IOException {
final int N = mPaths.size();
for (int i = 0; i < N; i++) {
- out.startTag(NAMESPACE, TAG_PATH);
- out.text(encodeSegments(mPaths.valueAt(i)));
- out.endTag(NAMESPACE, TAG_PATH);
+ final String[] segments = mPaths.valueAt(i);
+ if (segments != null) {
+ out.startTag(NAMESPACE, TAG_PATH);
+ out.text(encodeSegments(segments));
+ out.endTag(NAMESPACE, TAG_PATH);
+ }
}
}
diff --git a/services/core/java/com/android/server/slice/SlicePermissionManager.java b/services/core/java/com/android/server/slice/SlicePermissionManager.java
index 780bc96..315d5e3 100644
--- a/services/core/java/com/android/server/slice/SlicePermissionManager.java
+++ b/services/core/java/com/android/server/slice/SlicePermissionManager.java
@@ -315,7 +315,8 @@
return new AtomicFile(new File(mSliceDir, fileName));
}
- private void handlePersist() {
+ @VisibleForTesting
+ void handlePersist() {
synchronized (this) {
for (Persistable persistable : mDirty) {
AtomicFile file = getFile(persistable.getFileName());
@@ -335,7 +336,7 @@
out.flush();
file.finishWrite(stream);
- } catch (IOException | XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException | RuntimeException e) {
Slog.w(TAG, "Failed to save access file, restoring backup", e);
file.failWrite(stream);
}
@@ -344,6 +345,12 @@
}
}
+ // use addPersistableDirty(); this is just for tests
+ @VisibleForTesting
+ void addDirtyImmediate(Persistable obj) {
+ mDirty.add(obj);
+ }
+
private void handleRemove(PkgUser pkgUser) {
getFile(SliceClientPermissions.getFileName(pkgUser)).delete();
getFile(SliceProviderPermissions.getFileName(pkgUser)).delete();
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 973499f..1f638c7 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -37,6 +37,7 @@
import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
import static com.android.server.am.ActivityDisplayProto.ID;
import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
@@ -120,6 +121,9 @@
*/
private boolean mRemoved;
+ /** The display can only contain one task. */
+ private boolean mSingleTaskInstance;
+
/**
* A focusable stack that is purposely to be positioned at the top. Although the stack may not
* have the topmost index, it is used as a preferred candidate to prevent being unable to resume
@@ -244,6 +248,10 @@
final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
? getFocusedStack() : null;
final boolean wasContained = mStacks.remove(stack);
+ if (mSingleTaskInstance && getChildCount() > 0) {
+ throw new IllegalStateException(
+ "positionChildAt: Can only have one child on display=" + this);
+ }
final int insertPosition = getTopInsertPosition(stack, position);
mStacks.add(insertPosition, stack);
@@ -403,6 +411,14 @@
*/
<T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
+ if (mSingleTaskInstance && getChildCount() > 0) {
+ // Create stack on default display instead since this display can only contain 1 stack.
+ // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
+ // this goes away once ActivityView is no longer using virtual displays.
+ return mRootActivityContainer.getDefaultDisplay().createStack(
+ windowingMode, activityType, onTop);
+ }
+
if (activityType == ACTIVITY_TYPE_UNDEFINED) {
// Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
// anything else should be passing it in anyways...
@@ -1337,8 +1353,31 @@
}
}
+ void setDisplayToSingleTaskInstance() {
+ final int childCount = getChildCount();
+ if (childCount > 1) {
+ throw new IllegalArgumentException("Display already has multiple stacks. display="
+ + this);
+ }
+ if (childCount > 0) {
+ final ActivityStack stack = getChildAt(0);
+ if (stack.getChildCount() > 1) {
+ throw new IllegalArgumentException("Display stack already has multiple tasks."
+ + " display=" + this + " stack=" + stack);
+ }
+ }
+
+ mSingleTaskInstance = true;
+ }
+
+ /** Returns true if the display can only contain one task */
+ boolean isSingleTaskInstance() {
+ return mSingleTaskInstance;
+ }
+
public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
+ pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
+ + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
final String myPrefix = prefix + " ";
if (mHomeStack != null) {
pw.println(myPrefix + "mHomeStack=" + mHomeStack);
@@ -1373,6 +1412,7 @@
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
proto.write(ID, mDisplayId);
+ proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
final ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 6755c73..4581a0f 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -66,6 +66,8 @@
import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
+import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
@@ -309,7 +311,7 @@
* The first entry in the list is the least recently used.
* It contains HistoryRecord objects.
*/
- final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
+ private final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
/**
* When we are in the process of pausing an activity, before starting the
@@ -1142,6 +1144,12 @@
}
}
+ /** @return true if the stack can only contain one task */
+ boolean isSingleTaskInstance() {
+ final ActivityDisplay display = getDisplay();
+ return display != null && display.isSingleTaskInstance();
+ }
+
final void removeActivitiesFromLRUListLocked(TaskRecord task) {
for (ActivityRecord r : task.mActivities) {
mLRUActivities.remove(r);
@@ -5153,6 +5161,47 @@
}
}
+ boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
+ String dumpPackage, boolean needSep) {
+ pw.println(" Stack #" + mStackId
+ + ": type=" + activityTypeToString(getActivityType())
+ + " mode=" + windowingModeToString(getWindowingMode()));
+ pw.println(" isSleeping=" + shouldSleepActivities());
+ pw.println(" mBounds=" + getRequestedOverrideBounds());
+
+ boolean printed = dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
+ needSep);
+
+ printed |= dumpHistoryList(fd, pw, mLRUActivities, " ", "Run", false,
+ !dumpAll, false, dumpPackage, true,
+ " Running activities (most recent first):", null);
+
+ needSep = printed;
+ boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep,
+ " mPausingActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ pr = printThisActivity(pw, getResumedActivity(), dumpPackage, needSep,
+ " mResumedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ if (dumpAll) {
+ pr = printThisActivity(pw, mLastPausedActivity, dumpPackage, needSep,
+ " mLastPausedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = true;
+ }
+ printed |= printThisActivity(pw, mLastNoHistoryActivity, dumpPackage,
+ needSep, " mLastNoHistoryActivity: ");
+ }
+ return printed;
+ }
+
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, boolean needSep) {
@@ -5172,7 +5221,7 @@
pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
pw.println(prefix + "* " + task);
task.dump(pw, prefix + " ");
- ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
+ dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
}
return true;
@@ -5241,11 +5290,6 @@
* {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
*/
void removeTask(TaskRecord task, String reason, int mode) {
- // TODO(b/119259346): Move some logic below to TaskRecord. See bug for more context.
- for (ActivityRecord record : task.mActivities) {
- onActivityRemovedFromStack(record);
- }
-
final boolean removed = mTaskHistory.remove(task);
if (removed) {
@@ -5255,25 +5299,8 @@
removeActivitiesFromLRUListLocked(task);
updateTaskMovement(task, true);
- if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
- // This task is going away, so save the last state if necessary.
- task.saveLaunchingStateIfNeeded();
-
- // TODO: VI what about activity?
- final boolean isVoiceSession = task.voiceSession != null;
- if (isVoiceSession) {
- try {
- task.voiceSession.taskFinished(task.intent, task.taskId);
- } catch (RemoteException e) {
- }
- }
- if (task.autoRemoveFromRecents() || isVoiceSession) {
- // Task creator asked to remove this when done, or this task was a voice
- // interaction, so it should not remain on the recent tasks list.
- mStackSupervisor.mRecentTasks.remove(task);
- }
-
- task.removeWindowContainer();
+ if (mode == REMOVE_TASK_MODE_DESTROYING) {
+ task.cleanUpResourcesForDestroy();
}
if (mTaskHistory.isEmpty()) {
@@ -5348,6 +5375,10 @@
String reason) {
// TODO: Is this remove really needed? Need to look into the call path for the other addTask
mTaskHistory.remove(task);
+ if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) {
+ throw new IllegalStateException("Can only have one child on stack=" + this);
+ }
+
position = getAdjustedPositionForTask(task, position, null /* starting */);
final boolean toTop = position >= mTaskHistory.size();
final ActivityStack prevStack = preAddTask(task, reason, toTop);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c4be1ba537..86c5d4d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4569,6 +4569,26 @@
}
}
+ /**
+ * Makes the display with the given id a single task instance display. I.e the display can only
+ * contain one task.
+ */
+ @Override
+ public void setDisplayToSingleTaskInstance(int displayId) {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "setDisplayToSingleTaskInstance");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ final ActivityDisplay display =
+ mRootActivityContainer.getActivityDisplayOrCreate(displayId);
+ if (display != null) {
+ display.setDisplayToSingleTaskInstance();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a5ceee2..fecc8da 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2506,6 +2506,7 @@
mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mWindowingLayer.release();
mOverlayLayer.release();
+ mInputMonitor.onDisplayRemoved();
} finally {
mDisplayReady = false;
mRemovingDisplay = false;
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 45d77de..5cfa7de 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -326,15 +326,11 @@
void applySettingsToDisplayLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
+ final Entry entry = getOrCreateEntry(displayInfo);
// Setting windowing mode first, because it may override overscan values later.
dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId()));
- if (entry == null) {
- return;
- }
-
displayInfo.overscanLeft = entry.mOverscanLeft;
displayInfo.overscanTop = entry.mOverscanTop;
displayInfo.overscanRight = entry.mOverscanRight;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index fc1c65c..632db38 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -32,6 +32,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.graphics.Rect;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
@@ -45,7 +46,9 @@
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
+import android.view.animation.Animation;
+import com.android.server.AnimationThread;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
@@ -60,6 +63,7 @@
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
+ private boolean mUpdateInputWindowsPending;
// Currently focused input window handle.
private InputWindowHandle mFocusedInputWindowHandle;
@@ -70,8 +74,11 @@
new UpdateInputForAllWindowsConsumer();
private final int mDisplayId;
+ private final DisplayContent mDisplayContent;
+ private boolean mDisplayRemoved;
private final SurfaceControl.Transaction mInputTransaction;
+ private final Handler mHandler;
/**
* The set of input consumer added to the window manager by name, which consumes input events
@@ -105,10 +112,64 @@
}
}
+ private final Runnable mUpdateInputWindows = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mService.mGlobalLock) {
+ mUpdateInputWindowsPending = false;
+ mUpdateInputWindowsNeeded = false;
+
+ if (mDisplayRemoved) {
+ return;
+ }
+
+ // Populate the input window list with information about all of the windows that
+ // could potentially receive input.
+ // As an optimization, we could try to prune the list of windows but this turns
+ // out to be difficult because only the native code knows for sure which window
+ // currently has touch focus.
+
+ // If there's a drag in flight, provide a pseudo-window to catch drag input
+ final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
+ if (inDrag) {
+ if (DEBUG_DRAG) {
+ Log.d(TAG_WM, "Inserting drag window");
+ }
+ mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId);
+ } else {
+ mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId);
+ }
+
+ final boolean inPositioning =
+ mService.mTaskPositioningController.isPositioningLocked();
+ if (inPositioning) {
+ if (DEBUG_TASK_POSITIONING) {
+ Log.d(TAG_WM, "Inserting window handle for repositioning");
+ }
+ mService.mTaskPositioningController.showInputSurface(mInputTransaction,
+ mDisplayId);
+ } else {
+ mService.mTaskPositioningController.hideInputSurface(mInputTransaction,
+ mDisplayId);
+ }
+
+ // Add all windows on the default display.
+ mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
+ }
+ }
+ };
+
public InputMonitor(WindowManagerService service, int displayId) {
mService = service;
+ mDisplayContent = mService.mRoot.getDisplayContent(displayId);
mDisplayId = displayId;
- mInputTransaction = mService.mRoot.getDisplayContent(mDisplayId).getPendingTransaction();
+ mInputTransaction = mDisplayContent.getPendingTransaction();
+ mHandler = AnimationThread.getHandler();
+ }
+
+ void onDisplayRemoved() {
+ mHandler.removeCallbacks(mUpdateInputWindows);
+ mDisplayRemoved = true;
}
private void addInputConsumer(String name, InputConsumerImpl consumer) {
@@ -248,41 +309,18 @@
if (!force && !mUpdateInputWindowsNeeded) {
return;
}
- mUpdateInputWindowsNeeded = false;
+ scheduleUpdateInputWindows();
+ }
- if (false) Slog.d(TAG_WM, ">>>>>> ENTERED updateInputWindowsLw");
-
- // Populate the input window list with information about all of the windows that
- // could potentially receive input.
- // As an optimization, we could try to prune the list of windows but this turns
- // out to be difficult because only the native code knows for sure which window
- // currently has touch focus.
-
- // If there's a drag in flight, provide a pseudo-window to catch drag input
- final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
- if (inDrag) {
- if (DEBUG_DRAG) {
- Log.d(TAG_WM, "Inserting drag window");
- }
- mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId);
- } else {
- mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId);
+ private void scheduleUpdateInputWindows() {
+ if (mDisplayRemoved) {
+ return;
}
- final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked();
- if (inPositioning) {
- if (DEBUG_TASK_POSITIONING) {
- Log.d(TAG_WM, "Inserting window handle for repositioning");
- }
- mService.mTaskPositioningController.showInputSurface(mInputTransaction, mDisplayId);
- } else {
- mService.mTaskPositioningController.hideInputSurface(mInputTransaction, mDisplayId);
+ if (!mUpdateInputWindowsPending) {
+ mUpdateInputWindowsPending = true;
+ mHandler.post(mUpdateInputWindows);
}
-
- // Add all windows on the default display.
- mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);
-
- if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
/* Called when the current input focus changes.
@@ -385,19 +423,18 @@
mTmpRect.setEmpty();
mDisableWallpaperTouchEvents = false;
this.inDrag = inDrag;
- final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
- wallpaperController = dc.mWallpaperController;
+ wallpaperController = mDisplayContent.mWallpaperController;
resetInputConsumers(mInputTransaction);
- dc.forAllWindows(this,
+ mDisplayContent.forAllWindows(this,
true /* traverseTopToBottom */);
if (mAddWallpaperInputConsumerHandle) {
wallpaperInputConsumer.show(mInputTransaction, 0);
}
- dc.scheduleAnimation();
+ mDisplayContent.scheduleAnimation();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 6f92e64..f55c7c9 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -29,8 +29,6 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.activityTypeToString;
-import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -915,6 +913,13 @@
+ " to its current displayId=" + displayId);
}
+ if (activityDisplay.isSingleTaskInstance() && activityDisplay.getChildCount() > 0) {
+ // We don't allow moving stacks to single instance display that already has a child.
+ Slog.e(TAG, "Can not move stack=" + stack
+ + " to single task instance display=" + activityDisplay);
+ return;
+ }
+
stack.reparent(activityDisplay, onTop, false /* displayRemoved */);
// TODO(multi-display): resize stacks properly if moved from split-screen.
}
@@ -2301,42 +2306,7 @@
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
pw.println();
- pw.println(" Stack #" + stack.mStackId
- + ": type=" + activityTypeToString(stack.getActivityType())
- + " mode=" + windowingModeToString(stack.getWindowingMode()));
- pw.println(" isSleeping=" + stack.shouldSleepActivities());
- pw.println(" mBounds=" + stack.getRequestedOverrideBounds());
-
- printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
- needSep);
-
- printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
- !dumpAll, false, dumpPackage, true,
- " Running activities (most recent first):", null);
-
- needSep = printed;
- boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
- " mPausingActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
- " mResumedActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- if (dumpAll) {
- pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
- " mLastPausedActivity: ");
- if (pr) {
- printed = true;
- needSep = true;
- }
- printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
- needSep, " mLastNoHistoryActivity: ");
- }
+ printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
needSep = printed;
}
printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep,
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 8c80009..f1b0c0696 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -481,6 +481,32 @@
mTask = task;
}
+ void cleanUpResourcesForDestroy() {
+ if (!mActivities.isEmpty()) {
+ return;
+ }
+
+ // This task is going away, so save the last state if necessary.
+ saveLaunchingStateIfNeeded();
+
+ // TODO: VI what about activity?
+ final boolean isVoiceSession = voiceSession != null;
+ if (isVoiceSession) {
+ try {
+ voiceSession.taskFinished(intent, taskId);
+ } catch (RemoteException e) {
+ }
+ }
+ if (autoRemoveFromRecents() || isVoiceSession) {
+ // Task creator asked to remove this when done, or this task was a voice
+ // interaction, so it should not remain on the recent tasks list.
+ mService.mStackSupervisor.mRecentTasks.remove(this);
+ }
+
+ removeWindowContainer();
+ }
+
+ @VisibleForTesting
void removeWindowContainer() {
mService.getLockTaskController().clearLockedTask(this);
if (mTask == null) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 6d72191..b4fe837 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -111,6 +111,7 @@
"android.hardware.light@2.0",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
+ "android.hardware.power.stats@1.0",
"android.hardware.tetheroffload.config@1.0",
"android.hardware.thermal@1.0",
"android.hardware.tv.cec@1.0",
diff --git a/services/core/jni/BroadcastRadio/NativeCallbackThread.h b/services/core/jni/BroadcastRadio/NativeCallbackThread.h
index 53990be..0f62de9 100644
--- a/services/core/jni/BroadcastRadio/NativeCallbackThread.h
+++ b/services/core/jni/BroadcastRadio/NativeCallbackThread.h
@@ -41,7 +41,7 @@
DISALLOW_COPY_AND_ASSIGN(NativeCallbackThread);
public:
- NativeCallbackThread(JavaVM *vm);
+ explicit NativeCallbackThread(JavaVM *vm);
virtual ~NativeCallbackThread();
void enqueue(const Task &task);
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index 9c2e1e5..a2a7f7d 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -73,7 +73,8 @@
wp<V1_1::ITunerCallback> mTunerCallback;
public:
- HalDeathRecipient(wp<V1_1::ITunerCallback> tunerCallback):mTunerCallback(tunerCallback) {}
+ explicit HalDeathRecipient(wp<V1_1::ITunerCallback> tunerCallback)
+ : mTunerCallback(tunerCallback) {}
virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who);
};
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 0ff60e4..024760d 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -27,9 +27,11 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <unordered_map>
#include <android/hardware/power/1.0/IPower.h>
#include <android/hardware/power/1.1/IPower.h>
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
#include <android/system/suspend/1.0/ISystemSuspend.h>
#include <android/system/suspend/1.0/ISystemSuspendCallback.h>
#include <android_runtime/AndroidRuntime.h>
@@ -74,6 +76,33 @@
static jmethodID jputVoter = NULL;
static jmethodID jputState = NULL;
+std::mutex gPowerHalMutex;
+std::unordered_map<uint32_t, std::string> gPowerStatsHalEntityNames = {};
+std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>>
+ gPowerStatsHalStateNames = {};
+std::vector<uint32_t> gPowerStatsHalPlatformIds = {};
+std::vector<uint32_t> gPowerStatsHalSubsystemIds = {};
+sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0 = nullptr;
+std::function<void(JNIEnv*, jobject)> gGetLowPowerStatsImpl = {};
+std::function<jint(JNIEnv*, jobject)> gGetPlatformLowPowerStatsImpl = {};
+std::function<jint(JNIEnv*, jobject)> gGetSubsystemLowPowerStatsImpl = {};
+
+// The caller must be holding gPowerHalMutex.
+static void deinitPowerStatsLocked() {
+ gPowerStatsHalV1_0 = nullptr;
+}
+
+struct PowerHalDeathRecipient : virtual public hardware::hidl_death_recipient {
+ virtual void serviceDied(uint64_t cookie,
+ const wp<android::hidl::base::V1_0::IBase>& who) override {
+ // The HAL just died. Reset all handles to HAL services.
+ std::lock_guard<std::mutex> lock(gPowerHalMutex);
+ deinitPowerStatsLocked();
+ }
+};
+
+sp<PowerHalDeathRecipient> gDeathRecipient = new PowerHalDeathRecipient();
+
class WakeupCallback : public ISystemSuspendCallback {
public:
Return<void> notifyWakeup(bool success) override {
@@ -202,18 +231,291 @@
return mergedreasonpos - mergedreason;
}
-static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats) {
- if (jrpmStats == NULL) {
- jniThrowException(env, "java/lang/NullPointerException",
- "The rpmstats jni input jobject jrpmStats is null.");
- return;
+// The caller must be holding gPowerHalMutex.
+static bool checkResultLocked(const Return<void> &ret, const char* function) {
+ if (!ret.isOk()) {
+ ALOGE("%s failed: requested HAL service not available. Description: %s",
+ function, ret.description().c_str());
+ if (ret.isDeadObject()) {
+ deinitPowerStatsLocked();
+ }
+ return false;
}
- if (jgetAndUpdatePlatformState == NULL || jgetSubsystem == NULL
- || jputVoter == NULL || jputState == NULL) {
- ALOGE("A rpmstats jni jmethodID is null.");
+ return true;
+}
+
+// The caller must be holding gPowerHalMutex.
+// gPowerStatsHalV1_0 must not be null
+static bool initializePowerStats() {
+ using android::hardware::power::stats::V1_0::Status;
+ using android::hardware::power::stats::V1_0::PowerEntityType;
+
+ // Clear out previous content if we are re-initializing
+ gPowerStatsHalEntityNames.clear();
+ gPowerStatsHalStateNames.clear();
+ gPowerStatsHalPlatformIds.clear();
+ gPowerStatsHalSubsystemIds.clear();
+
+ Return<void> ret;
+ ret = gPowerStatsHalV1_0->getPowerEntityInfo([](auto infos, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGE("Error getting power entity info");
+ return;
+ }
+
+ // construct lookup table of powerEntityId to power entity name
+ // also construct vector of platform and subsystem IDs
+ for (auto info : infos) {
+ gPowerStatsHalEntityNames.emplace(info.powerEntityId, info.powerEntityName);
+ if (info.type == PowerEntityType::POWER_DOMAIN) {
+ gPowerStatsHalPlatformIds.emplace_back(info.powerEntityId);
+ } else {
+ gPowerStatsHalSubsystemIds.emplace_back(info.powerEntityId);
+ }
+ }
+ });
+ if (!checkResultLocked(ret, __func__)) {
+ return false;
+ }
+
+ ret = gPowerStatsHalV1_0->getPowerEntityStateInfo({}, [](auto stateSpaces, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGE("Error getting state info");
+ return;
+ }
+
+ // construct lookup table of powerEntityId, powerEntityStateId to power entity state name
+ for (auto stateSpace : stateSpaces) {
+ std::unordered_map<uint32_t, std::string> stateNames = {};
+ for (auto state : stateSpace.states) {
+ stateNames.emplace(state.powerEntityStateId,
+ state.powerEntityStateName);
+ }
+ gPowerStatsHalStateNames.emplace(stateSpace.powerEntityId, stateNames);
+ }
+ });
+ if (!checkResultLocked(ret, __func__)) {
+ return false;
+ }
+
+ return (!gPowerStatsHalEntityNames.empty()) && (!gPowerStatsHalStateNames.empty());
+}
+
+// The caller must be holding gPowerHalMutex.
+static bool getPowerStatsHalLocked() {
+ if (gPowerStatsHalV1_0 == nullptr) {
+ gPowerStatsHalV1_0 = android::hardware::power::stats::V1_0::IPowerStats::getService();
+ if (gPowerStatsHalV1_0 == nullptr) {
+ ALOGE("Unable to get power.stats HAL service.");
+ return false;
+ }
+
+ // Link death recipient to power.stats service handle
+ hardware::Return<bool> linked = gPowerStatsHalV1_0->linkToDeath(gDeathRecipient, 0);
+ if (!linked.isOk()) {
+ ALOGE("Transaction error in linking to power.stats HAL death: %s",
+ linked.description().c_str());
+ deinitPowerStatsLocked();
+ return false;
+ } else if (!linked) {
+ ALOGW("Unable to link to power.stats HAL death notifications");
+ // We should still continue even though linking failed
+ }
+ return initializePowerStats();
+ }
+ return true;
+}
+
+// The caller must be holding powerHalMutex.
+static void getPowerStatsHalLowPowerData(JNIEnv* env, jobject jrpmStats) {
+ using android::hardware::power::stats::V1_0::Status;
+
+ if (!getPowerStatsHalLocked()) {
+ ALOGE("failed to get low power stats");
return;
}
+ // Get power entity state residency data
+ bool success = false;
+ Return<void> ret = gPowerStatsHalV1_0->getPowerEntityStateResidencyData({},
+ [&env, &jrpmStats, &success](auto results, auto status) {
+ if (status == Status::NOT_SUPPORTED) {
+ ALOGW("getPowerEntityStateResidencyData is not supported");
+ success = false;
+ return;
+ }
+
+ for (auto result : results) {
+ jobject jsubsystem = env->CallObjectMethod(jrpmStats, jgetSubsystem,
+ env->NewStringUTF(gPowerStatsHalEntityNames.at(result.powerEntityId).c_str()));
+ if (jsubsystem == NULL) {
+ ALOGE("The rpmstats jni jobject jsubsystem is null.");
+ return;
+ }
+ for (auto stateResidency : result.stateResidencyData) {
+
+ env->CallVoidMethod(jsubsystem, jputState,
+ env->NewStringUTF(gPowerStatsHalStateNames.at(result.powerEntityId)
+ .at(stateResidency.powerEntityStateId).c_str()),
+ stateResidency.totalTimeInStateMs,
+ stateResidency.totalStateEntryCount);
+ }
+ }
+ success = true;
+ });
+ checkResultLocked(ret, __func__);
+ if (!success) {
+ ALOGE("getPowerEntityStateResidencyData failed");
+ }
+}
+
+static jint getPowerStatsHalPlatformData(JNIEnv* env, jobject outBuf) {
+ using android::hardware::power::stats::V1_0::Status;
+ using hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
+ using hardware::power::stats::V1_0::PowerEntityStateResidencyData;
+
+ if (!getPowerStatsHalLocked()) {
+ ALOGE("failed to get low power stats");
+ return -1;
+ }
+
+ char *output = (char*)env->GetDirectBufferAddress(outBuf);
+ char *offset = output;
+ int remaining = (int)env->GetDirectBufferCapacity(outBuf);
+ int total_added = -1;
+
+ // Get power entity state residency data
+ Return<void> ret = gPowerStatsHalV1_0->getPowerEntityStateResidencyData(
+ gPowerStatsHalPlatformIds,
+ [&offset, &remaining, &total_added](auto results, auto status) {
+ if (status == Status::NOT_SUPPORTED) {
+ ALOGW("getPowerEntityStateResidencyData is not supported");
+ return;
+ }
+
+ for (size_t i = 0; i < results.size(); i++) {
+ const PowerEntityStateResidencyResult& result = results[i];
+
+ for (size_t j = 0; j < result.stateResidencyData.size(); j++) {
+ const PowerEntityStateResidencyData& stateResidency =
+ result.stateResidencyData[j];
+ int added = snprintf(offset, remaining,
+ "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " ",
+ j + 1, gPowerStatsHalStateNames.at(result.powerEntityId)
+ .at(stateResidency.powerEntityStateId).c_str(),
+ stateResidency.totalTimeInStateMs,
+ stateResidency.totalStateEntryCount);
+ if (added < 0) {
+ break;
+ }
+ if (added > remaining) {
+ added = remaining;
+ }
+ offset += added;
+ remaining -= added;
+ total_added += added;
+ }
+ if (remaining <= 0) {
+ /* rewrite NULL character*/
+ offset--;
+ total_added--;
+ ALOGE("power.stats Hal: buffer not enough");
+ break;
+ }
+ }
+ });
+ if (!checkResultLocked(ret, __func__)) {
+ return -1;
+ }
+
+ total_added += 1;
+ return total_added;
+}
+
+static jint getPowerStatsHalSubsystemData(JNIEnv* env, jobject outBuf) {
+ using android::hardware::power::stats::V1_0::Status;
+ using hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
+ using hardware::power::stats::V1_0::PowerEntityStateResidencyData;
+
+ if (!getPowerStatsHalLocked()) {
+ ALOGE("failed to get low power stats");
+ return -1;
+ }
+
+ char *output = (char*)env->GetDirectBufferAddress(outBuf);
+ char *offset = output;
+ int remaining = (int)env->GetDirectBufferCapacity(outBuf);
+ int total_added = -1;
+
+ // Get power entity state residency data
+ Return<void> ret = gPowerStatsHalV1_0->getPowerEntityStateResidencyData(
+ gPowerStatsHalSubsystemIds,
+ [&offset, &remaining, &total_added](auto results, auto status) {
+ if (status == Status::NOT_SUPPORTED) {
+ ALOGW("getPowerEntityStateResidencyData is not supported");
+ return;
+ }
+
+ int added = snprintf(offset, remaining, "SubsystemPowerState ");
+ offset += added;
+ remaining -= added;
+ total_added += added;
+
+ for (size_t i = 0; i < results.size(); i++) {
+ const PowerEntityStateResidencyResult& result = results[i];
+ added = snprintf(offset, remaining, "subsystem_%zu name=%s ",
+ i + 1, gPowerStatsHalEntityNames.at(result.powerEntityId).c_str());
+ if (added < 0) {
+ break;
+ }
+
+ if (added > remaining) {
+ added = remaining;
+ }
+
+ offset += added;
+ remaining -= added;
+ total_added += added;
+
+ for (size_t j = 0; j < result.stateResidencyData.size(); j++) {
+ const PowerEntityStateResidencyData& stateResidency =
+ result.stateResidencyData[j];
+ added = snprintf(offset, remaining,
+ "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry=%"
+ PRIu64 " ", j + 1, gPowerStatsHalStateNames.at(result.powerEntityId)
+ .at(stateResidency.powerEntityStateId).c_str(),
+ stateResidency.totalTimeInStateMs,
+ stateResidency.totalStateEntryCount,
+ stateResidency.lastEntryTimestampMs);
+ if (added < 0) {
+ break;
+ }
+ if (added > remaining) {
+ added = remaining;
+ }
+ offset += added;
+ remaining -= added;
+ total_added += added;
+ }
+ if (remaining <= 0) {
+ /* rewrite NULL character*/
+ offset--;
+ total_added--;
+ ALOGE("power.stats Hal: buffer not enough");
+ break;
+ }
+ }
+ });
+ if (!checkResultLocked(ret, __func__)) {
+ return -1;
+ }
+
+ total_added += 1;
+ return total_added;
+}
+
+// The caller must be holding powerHalMutex.
+static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) {
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 == nullptr) {
ALOGE("Power Hal not loaded");
@@ -286,17 +588,12 @@
processPowerHalReturn(ret, "getSubsystemLowPowerStats");
}
-static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
+static jint getPowerHalPlatformData(JNIEnv* env, jobject outBuf) {
char *output = (char*)env->GetDirectBufferAddress(outBuf);
char *offset = output;
int remaining = (int)env->GetDirectBufferCapacity(outBuf);
int total_added = -1;
- if (outBuf == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", "null argument");
- return -1;
- }
-
{
sp<IPowerV1_0> powerHalV1_0 = getPowerHalV1_0();
if (powerHalV1_0 == nullptr) {
@@ -365,7 +662,7 @@
return total_added;
}
-static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
+static jint getPowerHalSubsystemData(JNIEnv* env, jobject outBuf) {
char *output = (char*)env->GetDirectBufferAddress(outBuf);
char *offset = output;
int remaining = (int)env->GetDirectBufferCapacity(outBuf);
@@ -374,11 +671,6 @@
// This is a IPower 1.1 API
sp<IPowerV1_1> powerHal_1_1 = nullptr;
- if (outBuf == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", "null argument");
- return -1;
- }
-
{
// Trying to get 1.1, this will succeed only for devices supporting 1.1
powerHal_1_1 = getPowerHalV1_1();
@@ -458,6 +750,88 @@
return total_added;
}
+static void setUpPowerStatsLocked() {
+ // First see if power.stats HAL is available. Fall back to power HAL if
+ // power.stats HAL is unavailable.
+ if (android::hardware::power::stats::V1_0::IPowerStats::getService() != nullptr) {
+ ALOGI("Using power.stats HAL");
+ gGetLowPowerStatsImpl = getPowerStatsHalLowPowerData;
+ gGetPlatformLowPowerStatsImpl = getPowerStatsHalPlatformData;
+ gGetSubsystemLowPowerStatsImpl = getPowerStatsHalSubsystemData;
+ } else if (android::hardware::power::V1_0::IPower::getService() != nullptr) {
+ ALOGI("Using power HAL");
+ gGetLowPowerStatsImpl = getPowerHalLowPowerData;
+ gGetPlatformLowPowerStatsImpl = getPowerHalPlatformData;
+ gGetSubsystemLowPowerStatsImpl = getPowerHalSubsystemData;
+ }
+}
+
+static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats) {
+ if (jrpmStats == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException",
+ "The rpmstats jni input jobject jrpmStats is null.");
+ return;
+ }
+ if (jgetAndUpdatePlatformState == NULL || jgetSubsystem == NULL
+ || jputVoter == NULL || jputState == NULL) {
+ ALOGE("A rpmstats jni jmethodID is null.");
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(gPowerHalMutex);
+
+ if (!gGetLowPowerStatsImpl) {
+ setUpPowerStatsLocked();
+ }
+
+ if (gGetLowPowerStatsImpl) {
+ return gGetLowPowerStatsImpl(env, jrpmStats);
+ }
+
+ ALOGE("Unable to load Power Hal or power.stats HAL");
+ return;
+}
+
+static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
+ if (outBuf == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", "null argument");
+ return -1;
+ }
+
+ std::lock_guard<std::mutex> lock(gPowerHalMutex);
+
+ if (!gGetPlatformLowPowerStatsImpl) {
+ setUpPowerStatsLocked();
+ }
+
+ if (gGetPlatformLowPowerStatsImpl) {
+ return gGetPlatformLowPowerStatsImpl(env, outBuf);
+ }
+
+ ALOGE("Unable to load Power Hal or power.stats HAL");
+ return -1;
+}
+
+static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
+ if (outBuf == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", "null argument");
+ return -1;
+ }
+
+ std::lock_guard<std::mutex> lock(gPowerHalMutex);
+
+ if (!gGetSubsystemLowPowerStatsImpl) {
+ setUpPowerStatsLocked();
+ }
+
+ if (gGetSubsystemLowPowerStatsImpl) {
+ return gGetSubsystemLowPowerStatsImpl(env, outBuf);
+ }
+
+ ALOGE("Unable to load Power Hal or power.stats HAL");
+ return -1;
+}
+
static const JNINativeMethod method_table[] = {
{ "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
{ "getLowPowerStats", "(Lcom/android/internal/os/RpmStats;)V", (void*)getLowPowerStats },
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index c22109c..b08d13f 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -89,7 +89,7 @@
private:
class HdmiCecCallback : public IHdmiCecCallback {
public:
- HdmiCecCallback(HdmiCecController* controller) : mController(controller) {};
+ explicit HdmiCecCallback(HdmiCecController* controller) : mController(controller) {};
Return<void> onCecMessage(const CecMessage& event) override;
Return<void> onHotplugEvent(const HotplugEvent& event) override;
private:
diff --git a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
index c8f842d..e519633 100644
--- a/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
+++ b/services/core/jni/com_android_server_storage_AppFuseBridge.cpp
@@ -74,7 +74,7 @@
}
}
- operator bool() {
+ explicit operator bool() {
return mLocked;
}
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 6c2a894..098b2ef 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -292,7 +292,7 @@
class TvInputCallback : public ITvInputCallback {
public:
- TvInputCallback(JTvInputHal* hal);
+ explicit TvInputCallback(JTvInputHal* hal);
Return<void> notify(const TvInputEvent& event) override;
private:
JTvInputHal* mHal;
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 7a5eaa8..f4443fe 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@
"android-support-test",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
+ "hamcrest-library",
"testables",
],
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index afbe6bc..9d84751 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -1015,6 +1015,22 @@
}
@Test
+ public void testCanceledNoisyNeverVibrate() throws Exception {
+ NotificationRecord r = getBuzzyBeepyNotification();
+
+ final int waitMs = mAudioManager.getFocusRampTimeMs(
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+ r.getAudioAttributes());
+
+ mService.buzzBeepBlinkLocked(r);
+ mService.clearNotifications();
+
+ verifyNeverVibrate();
+ Thread.sleep(waitMs);
+ verifyNeverVibrate();
+ }
+
+ @Test
public void testEmptyUriSoundTreatedAsNoSound() throws Exception {
NotificationChannel channel = new NotificationChannel("test", "test", IMPORTANCE_HIGH);
channel.setSound(Uri.EMPTY, null);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 659c6e7..8b65e76 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -859,6 +859,19 @@
assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("c/c")));
}
+ @Test
+ public void testOnPackagesChanged_nullValuesPassed_noNullPointers() {
+ for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+ ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+ mIpm, approvalLevel);
+ // null uid list
+ service.onPackagesChanged(true, new String[]{"this.is.a.package.name"}, null);
+
+ // null package list
+ service.onPackagesChanged(true, null, new int[]{103});
+ }
+ }
+
private void loadXml(ManagedServices service) throws Exception {
final StringBuffer xml = new StringBuffer();
xml.append("<" + service.getConfig().xmlTag + ">\n");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
new file mode 100644
index 0000000..fa90b29
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
@@ -0,0 +1,270 @@
+/*
+ * 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.notification;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertSame;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+// this is a lazy way to do in/out/err but we're not particularly interested in the output
+import static java.io.FileDescriptor.err;
+import static java.io.FileDescriptor.in;
+import static java.io.FileDescriptor.out;
+
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.Icon;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.UserHandle;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class NotificationShellCmdTest extends UiServiceTestCase {
+ private final Binder mBinder = new Binder();
+ private final ShellCallback mCallback = new ShellCallback();
+ private final TestableContext mTestableContext = spy(getContext());
+ @Mock
+ NotificationManagerService mMockService;
+ @Mock
+ INotificationManager mMockBinderService;
+ private TestableLooper mTestableLooper;
+ private ResultReceiver mResultReceiver;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mTestableLooper = TestableLooper.get(this);
+ mResultReceiver = new ResultReceiver(new Handler(mTestableLooper.getLooper()));
+
+ when(mMockService.getContext()).thenReturn(mTestableContext);
+ when(mMockService.getBinderService()).thenReturn(mMockBinderService);
+ }
+
+ private Bitmap createTestBitmap() {
+ final Bitmap bits = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(bits);
+ final GradientDrawable grad = new GradientDrawable(GradientDrawable.Orientation.TL_BR,
+ new int[]{Color.RED, Color.YELLOW, Color.GREEN,
+ Color.CYAN, Color.BLUE, Color.MAGENTA});
+ grad.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ grad.draw(canvas);
+ return bits;
+ }
+
+ private void doCmd(String... args) {
+ new NotificationShellCmd(mMockService)
+ .exec(mBinder, in, out, err, args, mCallback, mResultReceiver);
+ }
+
+ @Test
+ public void testNoArgs() throws Exception {
+ doCmd();
+ }
+
+ @Test
+ public void testHelp() throws Exception {
+ doCmd("--help");
+ }
+
+ Notification captureNotification(String aTag) throws Exception {
+ ArgumentCaptor<Notification> notificationCaptor =
+ ArgumentCaptor.forClass(Notification.class);
+ verify(mMockBinderService).enqueueNotificationWithTag(
+ eq(NotificationShellCmd.NOTIFICATION_PACKAGE),
+ eq("android"),
+ eq(aTag),
+ eq(NotificationShellCmd.NOTIFICATION_ID),
+ notificationCaptor.capture(),
+ eq(UserHandle.getCallingUserId()));
+ return notificationCaptor.getValue();
+ }
+
+ @Test
+ public void testBasic() throws Exception {
+ final String aTag = "aTag";
+ final String aText = "someText";
+ final String aTitle = "theTitle";
+ doCmd("notify",
+ "--title", aTitle,
+ aTag, aText);
+ final Notification captured = captureNotification(aTag);
+ assertEquals(aText, captured.extras.getString(Notification.EXTRA_TEXT));
+ assertEquals(aTitle, captured.extras.getString(Notification.EXTRA_TITLE));
+ }
+
+ @Test
+ public void testIcon() throws Exception {
+ final String aTag = "aTag";
+ final String aText = "someText";
+ doCmd("notify", "--icon", "@android:drawable/stat_sys_adb", aTag, aText);
+ final Notification captured = captureNotification(aTag);
+ final Icon icon = captured.getSmallIcon();
+ assertEquals("android", icon.getResPackage());
+ assertEquals(com.android.internal.R.drawable.stat_sys_adb, icon.getResId());
+ }
+
+ @Test
+ public void testBigText() throws Exception {
+ final String aTag = "aTag";
+ final String aText = "someText";
+ final String bigText = "someBigText";
+ doCmd("notify",
+ "--style", "bigtext",
+ "--big-text", bigText,
+ aTag, aText);
+ final Notification captured = captureNotification(aTag);
+ assertSame(captured.getNotificationStyle(), Notification.BigTextStyle.class);
+ assertEquals(aText, captured.extras.getString(Notification.EXTRA_TEXT));
+ assertEquals(bigText, captured.extras.getString(Notification.EXTRA_BIG_TEXT));
+ }
+
+ @Test
+ public void testBigPicture() throws Exception {
+ final String aTag = "aTag";
+ final String aText = "someText";
+ final String bigPicture = "@android:drawable/default_wallpaper";
+ doCmd("notify",
+ "--style", "bigpicture",
+ "--picture", bigPicture,
+ aTag, aText);
+ final Notification captured = captureNotification(aTag);
+ assertSame(captured.getNotificationStyle(), Notification.BigPictureStyle.class);
+ final Object pic = captured.extras.get(Notification.EXTRA_PICTURE);
+ assertThat(pic, instanceOf(Bitmap.class));
+ }
+
+ @Test
+ public void testInbox() throws Exception {
+ final int n = 25;
+ final String aTag = "inboxTag";
+ final String aText = "inboxText";
+ ArrayList<String> args = new ArrayList<>();
+ args.add("notify");
+ args.add("--style");
+ args.add("inbox");
+ final int startOfLineArgs = args.size();
+ for (int i = 0; i < n; i++) {
+ args.add("--line");
+ args.add(String.format("Line %02d", i));
+ }
+ args.add(aTag);
+ args.add(aText);
+
+ doCmd(args.toArray(new String[0]));
+ final Notification captured = captureNotification(aTag);
+ assertSame(captured.getNotificationStyle(), Notification.InboxStyle.class);
+ final Notification.Builder builder =
+ Notification.Builder.recoverBuilder(mContext, captured);
+ final ArrayList<CharSequence> lines =
+ ((Notification.InboxStyle) (builder.getStyle())).getLines();
+ for (int i = 0; i < n; i++) {
+ assertEquals(lines.get(i), args.get(1 + 2 * i + startOfLineArgs));
+ }
+ }
+
+ static final String[] PEOPLE = {
+ "Alice",
+ "Bob",
+ "Charlotte"
+ };
+ static final String[] MESSAGES = {
+ "Shall I compare thee to a summer's day?",
+ "Thou art more lovely and more temperate:",
+ "Rough winds do shake the darling buds of May,",
+ "And summer's lease hath all too short a date;",
+ "Sometime too hot the eye of heaven shines,",
+ "And often is his gold complexion dimm'd;",
+ "And every fair from fair sometime declines,",
+ "By chance or nature's changing course untrimm'd;",
+ "But thy eternal summer shall not fade,",
+ "Nor lose possession of that fair thou ow'st;",
+ "Nor shall death brag thou wander'st in his shade,",
+ "When in eternal lines to time thou grow'st:",
+ " So long as men can breathe or eyes can see,",
+ " So long lives this, and this gives life to thee.",
+ };
+
+ @Test
+ public void testMessaging() throws Exception {
+ final String aTag = "messagingTag";
+ final String aText = "messagingText";
+ ArrayList<String> args = new ArrayList<>();
+ args.add("notify");
+ args.add("--style");
+ args.add("messaging");
+ args.add("--conversation");
+ args.add("Sonnet 18");
+ final int startOfLineArgs = args.size();
+ for (int i = 0; i < MESSAGES.length; i++) {
+ args.add("--message");
+ args.add(String.format("%s:%s",
+ PEOPLE[i % PEOPLE.length],
+ MESSAGES[i % MESSAGES.length]));
+ }
+ args.add(aTag);
+ args.add(aText);
+
+ doCmd(args.toArray(new String[0]));
+ final Notification captured = captureNotification(aTag);
+ assertSame(Notification.MessagingStyle.class, captured.getNotificationStyle());
+ final Notification.Builder builder =
+ Notification.Builder.recoverBuilder(mContext, captured);
+ final Notification.MessagingStyle messagingStyle =
+ (Notification.MessagingStyle) (builder.getStyle());
+
+ assertEquals("Sonnet 18", messagingStyle.getConversationTitle());
+ final List<Notification.MessagingStyle.Message> messages = messagingStyle.getMessages();
+ for (int i = 0; i < messages.size(); i++) {
+ final Notification.MessagingStyle.Message m = messages.get(i);
+ assertEquals(MESSAGES[i], m.getText());
+ assertEquals(PEOPLE[i % PEOPLE.length], m.getSenderPerson().getName());
+ }
+
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
index dc057d5..b315e51 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SlicePermissionManagerTest.java
@@ -101,4 +101,34 @@
assertTrue(FileUtils.deleteContentsAndDir(sliceDir));
}
-}
\ No newline at end of file
+ @Test
+ public void testInvalid() throws Exception {
+ File sliceDir = new File(mContext.getCacheDir(), "slices-test");
+ if (!sliceDir.exists()) {
+ sliceDir.mkdir();
+ }
+ SlicePermissionManager permissions = new SlicePermissionManager(mContext,
+ TestableLooper.get(this).getLooper(), sliceDir);
+
+ DirtyTracker.Persistable junk = new DirtyTracker.Persistable() {
+ @Override
+ public String getFileName() {
+ return "invalidData";
+ }
+
+ @Override
+ public void writeTo(XmlSerializer out) throws IOException {
+ throw new RuntimeException("this doesn't work");
+ }
+ };
+
+ // let's put something bad in here
+ permissions.addDirtyImmediate(junk);
+ // force a persist. if this throws, it would take down system_server
+ permissions.handlePersist();
+
+ // Cleanup.
+ assertTrue(FileUtils.deleteContentsAndDir(sliceDir));
+ }
+
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 8e881b5..992d017 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -22,10 +22,10 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -43,11 +43,13 @@
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.policy.WindowManagerPolicy;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.MockitoSession;
import java.io.File;
@@ -94,6 +96,12 @@
@After
public void tearDown() {
deleteRecursively(TEST_FOLDER);
+
+ // TODO(b/121296525): We may want to restore other display settings (not only overscans in
+ // testPersistOverscan*test) on mPrimaryDisplay and mSecondaryDisplay back to default
+ // values after each test finishes, since we are going to reuse a singleton
+ // WindowManagerService instance among all tests that extend {@link WindowTestsBase} class
+ // (b/113239988).
}
@Test
@@ -245,21 +253,35 @@
@Test
public void testPersistOverscanInSameInstance() {
final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
- mTarget.setOverscanLocked(info, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ try {
+ mTarget.setOverscanLocked(info, 1 /* left */, 2 /* top */, 3 /* right */,
+ 4 /* bottom */);
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
- assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */,
+ 4 /* bottom */);
+ } finally {
+ mTarget.setOverscanLocked(info, 0, 0, 0, 0);
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ }
}
@Test
public void testPersistOverscanAcrossInstances() {
final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
- mTarget.setOverscanLocked(info, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ try {
+ mTarget.setOverscanLocked(info, 10 /* left */, 20 /* top */, 30 /* right */,
+ 40 /* bottom */);
- applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
- assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
+ assertOverscan(mPrimaryDisplay, 10 /* left */, 20 /* top */, 30 /* right */,
+ 40 /* bottom */);
+ } finally {
+ mTarget.setOverscanLocked(info, 0, 0, 0, 0);
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ }
}
@Test
@@ -389,26 +411,32 @@
mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
Surface.ROTATION_0);
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .startMocking();
final DisplayRotation displayRotation = mock(DisplayRotation.class);
- mPrimaryDisplay = spy(mPrimaryDisplay);
- when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+ spyOn(mPrimaryDisplay);
+ doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ mockitoSession.finishMocking();
}
@Test
public void testSetFixedToUserRotation() {
mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .startMocking();
final DisplayRotation displayRotation = mock(DisplayRotation.class);
- mPrimaryDisplay = spy(mPrimaryDisplay);
- when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+ spyOn(mPrimaryDisplay);
+ doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
applySettingsToDisplayByNewInstance(mPrimaryDisplay);
verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ mockitoSession.finishMocking();
}
private static void assertOverscan(DisplayContent display, int left, int top, int right,
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
index 5d675b7..7006075 100644
--- a/startop/view_compiler/TEST_MAPPING
+++ b/startop/view_compiler/TEST_MAPPING
@@ -2,6 +2,10 @@
"presubmit": [
{
"name": "dex-builder-test"
+ },
+ {
+ "name": "view-compiler-tests",
+ "host": true
}
]
}
diff --git a/startop/view_compiler/main.cc b/startop/view_compiler/main.cc
index 55bfdc7..609bcf3 100644
--- a/startop/view_compiler/main.cc
+++ b/startop/view_compiler/main.cc
@@ -32,6 +32,7 @@
namespace {
using namespace tinyxml2;
+using namespace startop::util;
using std::string;
constexpr char kStdoutFilename[]{"stdout"};
diff --git a/startop/view_compiler/util.cc b/startop/view_compiler/util.cc
index 69df41d..a0637e6 100644
--- a/startop/view_compiler/util.cc
+++ b/startop/view_compiler/util.cc
@@ -18,6 +18,9 @@
using std::string;
+namespace startop {
+namespace util {
+
// TODO: see if we can borrow this from somewhere else, like aapt2.
string FindLayoutNameFromFilename(const string& filename) {
size_t start = filename.rfind("/");
@@ -30,3 +33,6 @@
return filename.substr(start, end - start);
}
+
+} // namespace util
+} // namespace startop
diff --git a/startop/view_compiler/util.h b/startop/view_compiler/util.h
index 03e0939..0176175 100644
--- a/startop/view_compiler/util.h
+++ b/startop/view_compiler/util.h
@@ -13,11 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef UTIL_H_
-#define UTIL_H_
+#ifndef VIEW_COMPILER_UTIL_H_
+#define VIEW_COMPILER_UTIL_H_
#include <string>
+namespace startop {
+namespace util {
+
std::string FindLayoutNameFromFilename(const std::string& filename);
-#endif // UTIL_H_
+} // namespace util
+} // namespace startop
+
+#endif // VIEW_COMPILER_UTIL_H_
diff --git a/startop/view_compiler/util_test.cc b/startop/view_compiler/util_test.cc
index d1540d3..50682a0 100644
--- a/startop/view_compiler/util_test.cc
+++ b/startop/view_compiler/util_test.cc
@@ -20,9 +20,15 @@
using std::string;
+namespace startop {
+namespace util {
+
TEST(UtilTest, FindLayoutNameFromFilename) {
- EXPECT_EQ("bar", ::FindLayoutNameFromFilename("foo/bar.xml"));
- EXPECT_EQ("bar", ::FindLayoutNameFromFilename("bar.xml"));
- EXPECT_EQ("bar", ::FindLayoutNameFromFilename("./foo/bar.xml"));
- EXPECT_EQ("bar", ::FindLayoutNameFromFilename("/foo/bar.xml"));
+ EXPECT_EQ("bar", startop::util::FindLayoutNameFromFilename("foo/bar.xml"));
+ EXPECT_EQ("bar", startop::util::FindLayoutNameFromFilename("bar.xml"));
+ EXPECT_EQ("bar", startop::util::FindLayoutNameFromFilename("./foo/bar.xml"));
+ EXPECT_EQ("bar", startop::util::FindLayoutNameFromFilename("/foo/bar.xml"));
}
+
+} // namespace util
+} // namespace startop
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java
index 1548d6e..f7c60fc 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewActivity.java
@@ -20,6 +20,7 @@
import android.app.ActivityView;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Parcelable;
import android.widget.Button;
public class ActivityViewActivity extends Activity {
@@ -41,6 +42,10 @@
final Intent intent = Intent.makeMainActivity(null);
final Intent chooser = Intent.createChooser(intent,
"Pick an app to launch in ActivityView");
+ chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[] {
+ new Intent(Intent.ACTION_MAIN)
+ .addCategory("com.android.internal.category.PLATLOGO")
+ });
if (intent.resolveActivity(getPackageManager()) != null) {
chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
diff --git a/wifi/java/android/net/wifi/DppStatusCallback.java b/wifi/java/android/net/wifi/DppStatusCallback.java
new file mode 100644
index 0000000..fa2ab30
--- /dev/null
+++ b/wifi/java/android/net/wifi/DppStatusCallback.java
@@ -0,0 +1,166 @@
+/*
+ * 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 android.net.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.os.Handler;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * DPP Status Callback. Use this callback to get status updates (success, failure, progress)
+ * from the DPP operation started with {@link WifiManager#startDppAsConfiguratorInitiator(String,
+ * int, int, Handler, DppStatusCallback)} or {@link WifiManager#startDppAsEnrolleeInitiator(String,
+ * Handler, DppStatusCallback)}
+ * @hide
+ */
+@SystemApi
+public abstract class DppStatusCallback {
+ /**
+ * DPP Success event: Configuration sent (Configurator mode).
+ */
+ public static final int DPP_EVENT_SUCCESS_CONFIGURATION_SENT = 0;
+
+ /** @hide */
+ @IntDef(prefix = { "DPP_EVENT_SUCCESS_" }, value = {
+ DPP_EVENT_SUCCESS_CONFIGURATION_SENT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DppSuccessStatusCode {}
+
+ /**
+ * DPP Progress event: Initial authentication with peer succeeded.
+ */
+ public static final int DPP_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0;
+
+ /**
+ * DPP Progress event: Peer requires more time to process bootstrapping.
+ */
+ public static final int DPP_EVENT_PROGRESS_RESPONSE_PENDING = 1;
+
+ /** @hide */
+ @IntDef(prefix = { "DPP_EVENT_PROGRESS_" }, value = {
+ DPP_EVENT_PROGRESS_AUTHENTICATION_SUCCESS,
+ DPP_EVENT_PROGRESS_RESPONSE_PENDING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DppProgressStatusCode {}
+
+ /**
+ * DPP Failure event: Scanned QR code is either not a DPP URI, or the DPP URI has errors.
+ */
+ public static final int DPP_EVENT_FAILURE_INVALID_URI = -1;
+
+ /**
+ * DPP Failure event: Bootstrapping/Authentication initialization process failure.
+ */
+ public static final int DPP_EVENT_FAILURE_AUTHENTICATION = -2;
+
+ /**
+ * DPP Failure event: Both devices are implementing the same role and are incompatible.
+ */
+ public static final int DPP_EVENT_FAILURE_NOT_COMPATIBLE = -3;
+
+ /**
+ * DPP Failure event: Configuration process has failed due to malformed message.
+ */
+ public static final int DPP_EVENT_FAILURE_CONFIGURATION = -4;
+
+ /**
+ * DPP Failure event: DPP request while in another DPP exchange.
+ */
+ public static final int DPP_EVENT_FAILURE_BUSY = -5;
+
+ /**
+ * DPP Failure event: No response from the peer.
+ */
+ public static final int DPP_EVENT_FAILURE_TIMEOUT = -6;
+
+ /**
+ * DPP Failure event: General protocol failure.
+ */
+ public static final int DPP_EVENT_FAILURE = -7;
+
+ /**
+ * DPP Failure event: Feature or option is not supported.
+ */
+ public static final int DPP_EVENT_FAILURE_NOT_SUPPORTED = -8;
+
+ /**
+ * DPP Failure event: Invalid network provided to DPP configurator.
+ * Network must either be WPA3-Personal (SAE) or WPA2-Personal (PSK).
+ */
+ public static final int DPP_EVENT_FAILURE_INVALID_NETWORK = -9;
+
+
+ /** @hide */
+ @IntDef(prefix = {"DPP_EVENT_FAILURE_"}, value = {
+ DPP_EVENT_FAILURE_INVALID_URI,
+ DPP_EVENT_FAILURE_AUTHENTICATION,
+ DPP_EVENT_FAILURE_NOT_COMPATIBLE,
+ DPP_EVENT_FAILURE_CONFIGURATION,
+ DPP_EVENT_FAILURE_BUSY,
+ DPP_EVENT_FAILURE_TIMEOUT,
+ DPP_EVENT_FAILURE,
+ DPP_EVENT_FAILURE_NOT_SUPPORTED,
+ DPP_EVENT_FAILURE_INVALID_NETWORK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DppFailureStatusCode {
+ }
+
+ /**
+ * Called when local DPP Enrollee successfully receives a new Wi-Fi configuration from the
+ * peer DPP configurator. This callback marks the successful end of the DPP current DPP
+ * session, and no further callbacks will be called. This callback is the successful outcome
+ * of a DPP flow starting with {@link WifiManager#startDppAsEnrolleeInitiator(String, Handler,
+ * DppStatusCallback)}.
+ *
+ * @param newNetworkId New Wi-Fi configuration with a network ID received from the configurator
+ */
+ public abstract void onEnrolleeSuccess(int newNetworkId);
+
+ /**
+ * Called when a DPP success event takes place, except for when configuration is received from
+ * an external Configurator. The callback onSuccessConfigReceived will be used in this case.
+ * This callback marks the successful end of the current DPP session, and no further
+ * callbacks will be called. This callback is the successful outcome of a DPP flow starting with
+ * {@link WifiManager#startDppAsConfiguratorInitiator(String, int, int, Handler,
+ * DppStatusCallback)}.
+ *
+ * @param code DPP success status code.
+ */
+ public abstract void onConfiguratorSuccess(@DppSuccessStatusCode int code);
+
+ /**
+ * Called when a DPP Failure event takes place. This callback marks the unsuccessful end of the
+ * current DPP session, and no further callbacks will be called.
+ *
+ * @param code DPP failure status code.
+ */
+ public abstract void onFailure(@DppFailureStatusCode int code);
+
+ /**
+ * Called when DPP events that indicate progress take place. Can be used by UI elements
+ * to show progress.
+ *
+ * @param code DPP progress status code.
+ */
+ public abstract void onProgress(@DppProgressStatusCode int code);
+}
diff --git a/wifi/java/android/net/wifi/IDppCallback.aidl b/wifi/java/android/net/wifi/IDppCallback.aidl
new file mode 100644
index 0000000..c452c76
--- /dev/null
+++ b/wifi/java/android/net/wifi/IDppCallback.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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 android.net.wifi;
+
+/**
+ * Interface for DPP callback.
+ *
+ * @hide
+ */
+oneway interface IDppCallback
+{
+ /**
+ * Called when local DPP Enrollee successfully receives a new Wi-Fi configuratrion from the
+ * peer DPP configurator.
+ */
+ void onSuccessConfigReceived(int newNetworkId);
+
+ /**
+ * Called when DPP success events take place, except for when configuration is received from
+ * an external Configurator. The callback onSuccessConfigReceived will be used in this case.
+ */
+ void onSuccess(int status);
+
+ /**
+ * Called when DPP Failure events take place.
+ */
+ void onFailure(int status);
+
+ /**
+ * Called when DPP events that indicate progress take place. Can be used by UI elements
+ * to show progress.
+ */
+ void onProgress(int status);
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0362a1b..1700006 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -25,6 +25,7 @@
import android.net.DhcpInfo;
import android.net.Network;
+import android.net.wifi.IDppCallback;
import android.net.wifi.INetworkRequestMatchCallback;
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ITrafficStateCallback;
@@ -199,5 +200,13 @@
String[] getFactoryMacAddresses();
void setDeviceMobilityState(int state);
+
+ void startDppAsConfiguratorInitiator(in IBinder binder, in String enrolleeUri,
+ int selectedNetworkId, int netRole, in IDppCallback callback);
+
+ void startDppAsEnrolleeInitiator(in IBinder binder, in String configuratorUri,
+ in IDppCallback callback);
+
+ void stopDppSession();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index a7c2ff0..e67e8ea 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2017,6 +2017,8 @@
public static final int WIFI_FEATURE_OWE = 0x20000000; // Enhanced Open
/** @hide */
public static final int WIFI_FEATURE_LOW_LATENCY = 0x40000000; // Low Latency modes
+ /** @hide */
+ public static final int WIFI_FEATURE_DPP = 0x80000000; // DPP (Easy-Connect)
private int getSupportedFeatures() {
try {
@@ -4463,6 +4465,13 @@
}
/**
+ * @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect)
+ */
+ public boolean isDppSupported() {
+ return isFeatureSupported(WIFI_FEATURE_DPP);
+ }
+
+ /**
* Gets the factory Wi-Fi MAC addresses.
* @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array
* if failed.
@@ -4541,4 +4550,146 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /* DPP - Device Provisioning Protocol AKA "Easy Connect" */
+
+ /**
+ * DPP Network role: Station.
+ * @hide
+ */
+ @SystemApi
+ public static final int DPP_NETWORK_ROLE_STA = 0;
+
+ /**
+ * DPP Network role: Access Point.
+ * @hide
+ */
+ @SystemApi
+ public static final int DPP_NETWORK_ROLE_AP = 1;
+
+ /** @hide */
+ @IntDef(prefix = {"DPP_NETWORK_ROLE_"}, value = {
+ DPP_NETWORK_ROLE_STA,
+ DPP_NETWORK_ROLE_AP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DppNetworkRole {}
+
+ /**
+ * Start DPP in Configurator-Initiator role. The current device will initiate DPP bootstrapping
+ * with a peer, and configure the peer with the SSID and password of the specified network using
+ * the DPP protocol on an encrypted link.
+ *
+ * @param enrolleeUri URI of the Enrollee obtained separately (e.g. QR code scanning)
+ * @param selectedNetworkId Selected network ID to be sent to the peer
+ * @param enrolleeNetworkRole The network role of the enrollee
+ * @param callback Callback for status updates
+ * @param handler The handler on whose thread to execute the callbacks. Null for main thread.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void startDppAsConfiguratorInitiator(@NonNull String enrolleeUri,
+ int selectedNetworkId, @DppNetworkRole int enrolleeNetworkRole,
+ @Nullable Handler handler, @NonNull DppStatusCallback callback) {
+ Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
+ Binder binder = new Binder();
+ try {
+ mService.startDppAsConfiguratorInitiator(binder, enrolleeUri, selectedNetworkId,
+ enrolleeNetworkRole, new DppCallbackProxy(looper, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Start DPP in Enrollee-Initiator role. The current device will initiate DPP bootstrapping
+ * with a peer, and receive the SSID and password from the peer configurator.
+ *
+ * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning)
+ * @param callback Callback for status updates
+ * @param handler The handler on whose thread to execute the callbacks. Null for main thread.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void startDppAsEnrolleeInitiator(@NonNull String configuratorUri,
+ @Nullable Handler handler, @NonNull DppStatusCallback callback) {
+ Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
+ Binder binder = new Binder();
+ try {
+ mService.startDppAsEnrolleeInitiator(binder, configuratorUri,
+ new DppCallbackProxy(looper, callback));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Stop or abort a current DPP session.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void stopDppSession() {
+ try {
+ /* Request lower layers to stop/abort and clear resources */
+ mService.stopDppSession();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Helper class to support DPP callbacks
+ * @hide
+ */
+ @SystemApi
+ private static class DppCallbackProxy extends IDppCallback.Stub {
+ private final Handler mHandler;
+ private final DppStatusCallback mDppStatusCallback;
+
+ DppCallbackProxy(Looper looper, DppStatusCallback dppStatusCallback) {
+ mHandler = new Handler(looper);
+ mDppStatusCallback = dppStatusCallback;
+ }
+
+ @Override
+ public void onSuccessConfigReceived(int newNetworkId) {
+ Log.d(TAG, "DPP onSuccessConfigReceived callback");
+ mHandler.post(() -> {
+ mDppStatusCallback.onEnrolleeSuccess(newNetworkId);
+ });
+ }
+
+ @Override
+ public void onSuccess(int status) {
+ Log.d(TAG, "DPP onSuccess callback");
+ mHandler.post(() -> {
+ mDppStatusCallback.onConfiguratorSuccess(status);
+ });
+ }
+
+ @Override
+ public void onFailure(int status) {
+ Log.d(TAG, "DPP onFailure callback");
+ mHandler.post(() -> {
+ mDppStatusCallback.onFailure(status);
+ });
+ }
+
+ @Override
+ public void onProgress(int status) {
+ Log.d(TAG, "DPP onProgress callback");
+ mHandler.post(() -> {
+ mDppStatusCallback.onProgress(status);
+ });
+ }
+ }
}