Merge tag 'android-15.0.0_r32' of https://android.googlesource.com/platform/frameworks/base into HEAD
Android 15.0.0 Release 32 (BP1A.250505.005)
Change-Id: I0eebb6a89cdb74ec9daf96eb529517f6f88d154d
diff --git a/Android.bp b/Android.bp
index 529da53..d2f16e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -147,6 +147,7 @@
":statslog-framework-java-gen", // FrameworkStatsLog.java
":statslog-hwui-java-gen", // HwuiStatsLog.java
":audio_policy_configuration_V7_0",
+ "//packages/apps/OmniLib:omnirom-internal",
] + select(release_flag("RELEASE_ATTEST_MODULES"), {
true: [
":android.hardware.security.keymint-V4-java-source",
@@ -287,6 +288,7 @@
":framework-non-updatable-sources",
"core/java/**/*.logtags",
":apex-info-list",
+ "//packages/apps/OmniLib:omnirom-internal",
],
aidl: {
generate_get_transaction_name: true,
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 6902d6d..7765d20 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -60,6 +60,7 @@
namespace {
constexpr std::string_view kFrameworkPath = "/system/framework/framework-res.apk";
+constexpr std::string_view kOmniRomPath = "/system/framework/omnirom-res.apk";
Status ok() {
return Status::ok();
@@ -213,9 +214,10 @@
idmap2::Result<Idmap2Service::TargetResourceContainerPtr> Idmap2Service::GetTargetContainer(
const std::string& target_path) {
const bool is_framework = target_path == kFrameworkPath;
+ const bool is_OmniRomPath = target_path == kOmniRomPath;
bool use_cache;
struct stat st = {};
- if (is_framework || !::stat(target_path.c_str(), &st)) {
+ if (is_framework || is_OmniRomPath || !::stat(target_path.c_str(), &st)) {
use_cache = true;
} else {
LOG(WARNING) << "failed to stat target path '" << target_path << "' for the cache";
@@ -226,7 +228,7 @@
std::lock_guard lock(container_cache_mutex_);
if (auto cache_it = container_cache_.find(target_path); cache_it != container_cache_.end()) {
const auto& item = cache_it->second;
- if (is_framework ||
+ if (is_framework || is_OmniRomPath ||
(item.dev == st.st_dev && item.inode == st.st_ino && item.size == st.st_size
&& item.mtime.tv_sec == st.st_mtim.tv_sec && item.mtime.tv_nsec == st.st_mtim.tv_nsec)) {
return {item.apk};
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 3d85ea6..5398f57 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1457,7 +1457,7 @@
false, false);
for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
final int id = packageIdentifiers.keyAt(i);
- if (id == 0x01 || id == 0x7f) {
+ if (id == 0x01 || id == 0x7f || id == 0x3f) {
continue;
}
diff --git a/core/java/android/app/admin/SystemUpdateInfo.java b/core/java/android/app/admin/SystemUpdateInfo.java
index 9e6c91f..e5a3825 100644
--- a/core/java/android/app/admin/SystemUpdateInfo.java
+++ b/core/java/android/app/admin/SystemUpdateInfo.java
@@ -133,7 +133,7 @@
out.startTag(null, tag);
out.attributeLong(null, ATTR_RECEIVED_TIME, mReceivedTime);
out.attributeInt(null, ATTR_SECURITY_PATCH_STATE, mSecurityPatchState);
- out.attribute(null, ATTR_ORIGINAL_BUILD , Build.FINGERPRINT);
+ out.attribute(null, ATTR_ORIGINAL_BUILD , String.valueOf(Build.TIME));
out.endTag(null, tag);
}
@@ -142,7 +142,7 @@
public static SystemUpdateInfo readFromXml(TypedXmlPullParser parser) {
// If an OTA has been applied (build fingerprint has changed), discard stale info.
final String buildFingerprint = parser.getAttributeValue(null, ATTR_ORIGINAL_BUILD );
- if (!Build.FINGERPRINT.equals(buildFingerprint)) {
+ if (!String.valueOf(Build.TIME).equals(buildFingerprint)) {
return null;
}
try {
diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java
index ff80e61..f6420bc 100644
--- a/core/java/android/content/pm/PackagePartitions.java
+++ b/core/java/android/content/pm/PackagePartitions.java
@@ -131,7 +131,7 @@
final String partitionName = SYSTEM_PARTITIONS.get(i).getName();
digestProperties[i] = "ro." + partitionName + ".build.fingerprint";
}
- digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.fingerprint"; // build fingerprint
+ digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.date.utc"; // build fingerprint
return SystemProperties.digestOf(digestProperties);
}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index bbfae81..cbb4cbb 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -81,6 +81,7 @@
public static final String FRAMEWORK_APK_PATH = getFrameworkApkPath();
private static final String FRAMEWORK_APK_PATH_DEVICE = "/system/framework/framework-res.apk";
private static final String FRAMEWORK_APK_PATH_RAVENWOOD = "ravenwood-data/framework-res.apk";
+ private static final String OMNIROM_APK_PATH = "/system/framework/omnirom-res.apk";
private static final Object sSync = new Object();
@@ -288,6 +289,7 @@
for (String idmapPath : systemIdmapPaths) {
apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, ApkAssets.PROPERTY_SYSTEM));
}
+ apkAssets.add(ApkAssets.loadFromPath(OMNIROM_APK_PATH, ApkAssets.PROPERTY_SYSTEM));
sSystemApkAssetsSet = new ArraySet<>(apkAssets);
sSystemApkAssets = apkAssets.toArray(new ApkAssets[0]);
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 7361d4f..0f49428 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -31,6 +31,8 @@
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.util.Map;
/**
@@ -55,7 +57,8 @@
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
- Settings.Secure.DOZE_TAP_SCREEN_GESTURE
+ Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
+ OmniSettings.OMNI_DOZE_ON_CHARGE
};
/** Non-user configurable doze settings */
@@ -231,8 +234,7 @@
*/
@TestApi
public boolean alwaysOnEnabled(int user) {
- return boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0)
- && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
+ return alwaysOnEnabledSetting(user) || alwaysOnChargingEnabled(user);
}
/**
@@ -343,4 +345,25 @@
private void putDozeSetting(String name, String value, int userId) {
Settings.Secure.putStringForUser(mContext.getContentResolver(), name, value, userId);
}
+
+ // omni additions start
+ private boolean boolSettingSystem(String name, int user, int def) {
+ return Settings.System.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
+ }
+
+ /** @hide */
+ public boolean alwaysOnEnabledSetting(int user) {
+ boolean alwaysOnEnabled = boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0);
+ return alwaysOnEnabled && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
+ }
+
+ /** @hide */
+ public boolean alwaysOnChargingEnabled(int user) {
+ final boolean dozeOnChargeEnabled = boolSettingSystem(OmniSettings.OMNI_DOZE_ON_CHARGE, user, 0);
+ if (dozeOnChargeEnabled) {
+ final boolean dozeOnChargeEnabledNow = boolSettingSystem(OmniSettings.OMNI_DOZE_ON_CHARGE_NOW, user, 0);
+ return dozeOnChargeEnabledNow && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
+ }
+ return false;
+ }
}
diff --git a/core/java/android/hardware/fingerprint/HidlFingerprintSensorConfig.java b/core/java/android/hardware/fingerprint/HidlFingerprintSensorConfig.java
index d481153..9febcab 100644
--- a/core/java/android/hardware/fingerprint/HidlFingerprintSensorConfig.java
+++ b/core/java/android/hardware/fingerprint/HidlFingerprintSensorConfig.java
@@ -17,7 +17,9 @@
package android.hardware.fingerprint;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.TypedArray;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.common.CommonProps;
@@ -25,16 +27,22 @@
import android.hardware.biometrics.fingerprint.FingerprintSensorType;
import android.hardware.biometrics.fingerprint.SensorLocation;
import android.hardware.biometrics.fingerprint.SensorProps;
+import android.util.Slog;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Parse HIDL fingerprint sensor config and map it to SensorProps.aidl to match AIDL.
* See core/res/res/values/config.xml config_biometric_sensors
* @hide
*/
public final class HidlFingerprintSensorConfig extends SensorProps {
+ private static final String TAG = "HidlFingerprintSensorConfig";
+
private int mSensorId;
private int mModality;
private int mStrength;
@@ -70,6 +78,10 @@
halControlsIllumination = false;
sensorLocations = new SensorLocation[1];
+ // Non-empty workaroundLocations indicates that the sensor is SFPS.
+ final List<SensorLocation> workaroundLocations =
+ getWorkaroundSensorProps(context);
+
final int[] udfpsProps = context.getResources().getIntArray(
com.android.internal.R.array.config_udfps_sensor_props);
final boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps);
@@ -78,7 +90,7 @@
R.bool.config_is_powerbutton_fps);
if (isUdfps) {
- sensorType = FingerprintSensorType.UNKNOWN;
+ sensorType = FingerprintSensorType.UNDER_DISPLAY_OPTICAL;
} else if (isPowerbuttonFps) {
sensorType = FingerprintSensorType.POWER_BUTTON;
} else {
@@ -87,6 +99,9 @@
if (isUdfps && udfpsProps.length == 3) {
setSensorLocation(udfpsProps[0], udfpsProps[1], udfpsProps[2]);
+ } else if (!workaroundLocations.isEmpty()) {
+ sensorLocations = new SensorLocation[workaroundLocations.size()];
+ workaroundLocations.toArray(sensorLocations);
} else {
setSensorLocation(540 /* sensorLocationX */, 1636 /* sensorLocationY */,
130 /* sensorRadius */);
@@ -103,6 +118,48 @@
sensorLocations[0].sensorRadius = sensorRadius;
}
+ // TODO(b/174868353): workaround for gaps in HAL interface (remove and get directly from HAL)
+ // reads values via an overlay instead of querying the HAL
+ @NonNull
+ public static List<SensorLocation> getWorkaroundSensorProps(@NonNull Context context) {
+ final List<SensorLocation> sensorLocations = new ArrayList<>();
+
+ final TypedArray sfpsProps = context.getResources().obtainTypedArray(
+ com.android.internal.R.array.config_sfps_sensor_props);
+ for (int i = 0; i < sfpsProps.length(); i++) {
+ final int id = sfpsProps.getResourceId(i, -1);
+ if (id > 0) {
+ final SensorLocation location = parseSensorLocation(
+ context.getResources().obtainTypedArray(id));
+ if (location != null) {
+ sensorLocations.add(location);
+ }
+ }
+ }
+ sfpsProps.recycle();
+
+ return sensorLocations;
+ }
+
+ @Nullable
+ private static SensorLocation parseSensorLocation(@Nullable TypedArray array) {
+ if (array == null) {
+ return null;
+ }
+
+ try {
+ SensorLocation sensorLocation = new SensorLocation();
+ sensorLocation.display = array.getString(0);
+ sensorLocation.sensorLocationX = array.getInt(1, 0);
+ sensorLocation.sensorLocationY = array.getInt(2, 0);
+ sensorLocation.sensorRadius = array.getInt(3, 0);
+ return sensorLocation;
+ } catch (Exception e) {
+ Slog.w(TAG, "malformed sensor location", e);
+ }
+ return null;
+ }
+
private byte authenticatorStrengthToPropertyStrength(
@BiometricManager.Authenticators.Types int strength) {
switch (strength) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c41e626..9923e54 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1995,8 +1995,7 @@
// STATES2 bits that are used for Power Stats tracking
public static final int IMPORTANT_FOR_POWER_STATS_STATES2 =
- STATE2_VIDEO_ON_FLAG | STATE2_FLASHLIGHT_FLAG | STATE2_CAMERA_FLAG
- | STATE2_GPS_SIGNAL_QUALITY_MASK;
+ STATE2_VIDEO_ON_FLAG | STATE2_FLASHLIGHT_FLAG | STATE2_CAMERA_FLAG;
public static final int GNSS_SIGNAL_QUALITY_NONE = 2;
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 4cac4dee..00ebcf1 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -115,6 +115,7 @@
@UnsupportedAppUsage
void reboot(boolean confirm, String reason, boolean wait);
void rebootSafeMode(boolean confirm, boolean wait);
+ void rebootCustom(boolean confirm, String reason, boolean wait);
void shutdown(boolean confirm, String reason, boolean wait);
void crash(String message);
int getLastShutdownReason();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cd48f08..88a4496 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -864,6 +864,17 @@
public static final String REBOOT_RECOVERY = "recovery";
/**
+ * The value to pass as the 'reason' argument to reboot() to
+ * reboot into bootloader mode
+ * <p>
+ * Requires the permission
+ * {@link android.Manifest.permission#REBOOT}).
+ * </p>
+ * @hide
+ */
+ public static final String REBOOT_BOOTLOADER = "bootloader";
+
+ /**
* The value to pass as the 'reason' argument to reboot() to reboot into
* recovery mode for applying system updates.
* <p>
@@ -876,6 +887,17 @@
public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
/**
+ * The value to pass as the 'reason' argument to reboot() to
+ * reboot into fastboot mode
+ * <p>
+ * Requires the permission
+ * {@link android.Manifest.permission#REBOOT}).
+ * </p>
+ * @hide
+ */
+ public static final String REBOOT_FASTBOOT = "fastboot";
+
+ /**
* The value to pass as the 'reason' argument to reboot() when device owner requests a reboot on
* the device.
* @hide
@@ -1929,6 +1951,24 @@
}
/**
+ * Reboot the device with custom progress meassges.
+ * Will not return if the reboot is successful.
+ * <p>
+ * Requires the {@link android.Manifest.permission#REBOOT} permission.
+ * </p>
+ *
+ * @param reason code to pass to the kernel (e.g., "recovery") to
+ * request special boot modes, or null.
+ * @hide
+ */
+ public void rebootCustom(String reason) {
+ try {
+ mService.rebootCustom(false, reason, true);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Returns true if the device is currently in power save mode. When in this mode,
* applications should reduce their functionality in order to conserve battery as
* much as possible. You can monitor for changes to this state with
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 2473de4..614a981 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -264,6 +264,9 @@
private List<SplitPermissionInfo> mSplitPermissionInfos;
+ private static String[] sLocationProviderPkgNames;
+ private static String[] sLocationExtraPkgNames;
+
/**
* Creates a new instance.
*
@@ -1367,6 +1370,16 @@
pkgNames.add(exemptedPackage);
}
}
+ for (String pkgName: sLocationProviderPkgNames) {
+ if (pkgName != null) {
+ pkgNames.add(pkgName);
+ }
+ }
+ for (String pkgName: sLocationExtraPkgNames) {
+ if (pkgName != null) {
+ pkgNames.add(pkgName);
+ }
+ }
return pkgNames;
}
@@ -1382,6 +1395,10 @@
for (int i = 0; i < EXEMPTED_ROLES.length; i++) {
INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]);
}
+ sLocationProviderPkgNames = context.getResources().getStringArray(
+ R.array.config_locationProviderPackageNames);
+ sLocationExtraPkgNames = context.getResources().getStringArray(
+ R.array.config_locationExtraPackageNames);
}
}
/**
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index e15244a..3576ec8 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -33,6 +33,7 @@
* <p>
* If the user chooses the "Default" item, the saved string will be one of
* {@link System#DEFAULT_RINGTONE_URI},
+ * {@link System#DEFAULT_RINGTONE2_URI},
* {@link System#DEFAULT_NOTIFICATION_URI}, or
* {@link System#DEFAULT_ALARM_ALERT_URI}. If the user chooses the "Silent"
* item, the saved string will be an empty string.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4acb631..82d2612c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5663,6 +5663,16 @@
public static final String RINGTONE = "ringtone";
/**
+ * Persistent store for the system-wide default ringtone for Slot2 URI.
+ *
+ * @see #RINGTONE
+ * @see #DEFAULT_RINGTONE2_URI
+ *
+ */
+ /** {@hide} */
+ public static final String RINGTONE2 = "ringtone2";
+
+ /**
* A {@link Uri} that will point to the current default ringtone at any
* given time.
* <p>
@@ -5672,11 +5682,26 @@
*/
public static final Uri DEFAULT_RINGTONE_URI = getUriFor(RINGTONE);
+ /**
+ * A {@link Uri} that will point to the current default ringtone for Slot2
+ * at any given time.
+ *
+ * @see #DEFAULT_RINGTONE_URI
+ *
+ */
+ /** {@hide} */
+ public static final Uri DEFAULT_RINGTONE2_URI = getUriFor(RINGTONE2);
+
/** {@hide} */
public static final String RINGTONE_CACHE = "ringtone_cache";
/** {@hide} */
public static final Uri RINGTONE_CACHE_URI = getUriFor(RINGTONE_CACHE);
+ /** {@hide} */
+ public static final String RINGTONE2_CACHE = "ringtone2_cache";
+ /** {@hide} */
+ public static final Uri RINGTONE2_CACHE_URI = getUriFor(RINGTONE2_CACHE);
+
/**
* Persistent store for the system-wide default notification sound.
*
@@ -6493,6 +6518,7 @@
PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO);
PUBLIC_SETTINGS.add(VOLUME_ASSISTANT);
PUBLIC_SETTINGS.add(RINGTONE);
+ PUBLIC_SETTINGS.add(RINGTONE2);
PUBLIC_SETTINGS.add(NOTIFICATION_SOUND);
PUBLIC_SETTINGS.add(ALARM_ALERT);
PUBLIC_SETTINGS.add(TEXT_AUTO_REPLACE);
@@ -6616,6 +6642,7 @@
public static final Map<String, String> CLONE_FROM_PARENT_ON_VALUE = new ArrayMap<>();
static {
CLONE_FROM_PARENT_ON_VALUE.put(RINGTONE, Secure.SYNC_PARENT_SOUNDS);
+ CLONE_FROM_PARENT_ON_VALUE.put(RINGTONE2, Secure.SYNC_PARENT_SOUNDS);
CLONE_FROM_PARENT_ON_VALUE.put(NOTIFICATION_SOUND, Secure.SYNC_PARENT_SOUNDS);
CLONE_FROM_PARENT_ON_VALUE.put(ALARM_ALERT, Secure.SYNC_PARENT_SOUNDS);
}
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index e9bb28c..bf25453 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -99,4 +99,9 @@
default void onDreamingStopped() {
}
}
+
+ /**
+ * Called by the power manager to determine whether the dream has gone to doze mode.
+ */
+ public abstract boolean isDozing();
}
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index 1c0a2c0..e3a58a8 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -36,6 +36,7 @@
void testDream(int userId, in ComponentName componentName);
@UnsupportedAppUsage
boolean isDreaming();
+ boolean isDozing();
@UnsupportedAppUsage
boolean isDreamingOrInPreview();
boolean canStartDreaming(boolean isScreenOn);
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index a8aea7c..ef63c8f 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -507,7 +507,7 @@
for (String value : prefValues) {
final int delimiter = value.indexOf(':');
if (delimiter > 0) {
- if (engineName.equals(value.substring(0, delimiter))) {
+ if ((value.substring(0, delimiter)).equals(engineName)) {
return value.substring(delimiter + 1);
}
}
@@ -560,7 +560,7 @@
for (String value : prefValues) {
final int delimiter = value.indexOf(':');
if (delimiter > 0) {
- if (key.equals(value.substring(0, delimiter))) {
+ if (value.substring(0, delimiter).equals(key)) {
if (first) {
first = false;
} else {
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
index 38593b4..86e7e30 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -489,13 +489,14 @@
* precedence.
*/
@VisibleForTesting
- public ArrayList<IdmapInvocation> getImmutableFrameworkOverlayIdmapInvocations() {
+ public ArrayList<IdmapInvocation> getImmutableFrameworkOverlayIdmapInvocations(
+ String packageName) {
final ArrayList<IdmapInvocation> idmapInvocations = new ArrayList<>();
final ArrayList<Configuration> sortedConfigs = getSortedOverlays();
for (int i = 0, n = sortedConfigs.size(); i < n; i++) {
final Configuration overlay = sortedConfigs.get(i);
if (overlay.parsedConfig.mutable || !overlay.parsedConfig.enabled
- || !"android".equals(overlay.parsedConfig.parsedInfo.targetPackageName)) {
+ || !packageName.equals(overlay.parsedConfig.parsedInfo.targetPackageName)) {
continue;
}
@@ -534,26 +535,32 @@
*/
@NonNull
public String[] createImmutableFrameworkIdmapsInZygote() {
- final String targetPath = AssetManager.FRAMEWORK_APK_PATH;
final ArrayList<String> idmapPaths = new ArrayList<>();
- final ArrayList<IdmapInvocation> idmapInvocations =
- getImmutableFrameworkOverlayIdmapInvocations();
- for (int i = 0, n = idmapInvocations.size(); i < n; i++) {
- final IdmapInvocation invocation = idmapInvocations.get(i);
- final String[] idmaps = createIdmap(targetPath,
- invocation.overlayPaths.toArray(new String[0]),
- new String[]{OverlayConfigParser.OverlayPartition.POLICY_PUBLIC,
- invocation.policy},
- invocation.enforceOverlayable);
+ for (Map.Entry<String, String> target : new HashMap<String, String>() {{
+ put(AssetManager.FRAMEWORK_APK_PATH, "android");
+ put("/system/framework/omnirom-res.apk", "omnirom.platform");
+ }}.entrySet()) {
+ final String targetPath = target.getKey();
+ final String targetPackageName = target.getValue();
+ final ArrayList<IdmapInvocation> idmapInvocations =
+ getImmutableFrameworkOverlayIdmapInvocations(targetPackageName);
+ for (int i = 0, n = idmapInvocations.size(); i < n; i++) {
+ final IdmapInvocation invocation = idmapInvocations.get(i);
+ final String[] idmaps = createIdmap(targetPath,
+ invocation.overlayPaths.toArray(new String[0]),
+ new String[]{OverlayConfigParser.OverlayPartition.POLICY_PUBLIC,
+ invocation.policy},
+ invocation.enforceOverlayable);
- if (idmaps == null) {
- Log.w(TAG, "'idmap2 create-multiple' failed: no mutable=\"false\" overlays"
- + " targeting \"android\" will be loaded");
- return new String[0];
+ if (idmaps == null) {
+ Log.w(TAG, "'idmap2 create-multiple' failed: no mutable=\"false\" overlays"
+ + " targeting \"android\" will be loaded");
+ return new String[0];
+ }
+
+ idmapPaths.addAll(Arrays.asList(idmaps));
}
-
- idmapPaths.addAll(Arrays.asList(idmaps));
}
return idmapPaths.toArray(new String[0]);
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 4aebde5..8ec6a03 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -109,7 +109,7 @@
DEVELOPER_IMPORTANT,
context.getString(R.string.notification_channel_developer_important),
NotificationManager.IMPORTANCE_HIGH);
- developer.setBlockable(true);
+ developerImportant.setBlockable(true);
channelsList.add(developerImportant);
final NotificationChannel updates = new NotificationChannel(
@@ -143,6 +143,7 @@
VPN,
context.getString(R.string.notification_channel_vpn),
NotificationManager.IMPORTANCE_LOW);
+ vpn.setBlockable(true);
channelsList.add(vpn);
final NotificationChannel deviceAdmin = new NotificationChannel(
@@ -167,6 +168,7 @@
USB,
context.getString(R.string.notification_channel_usb),
NotificationManager.IMPORTANCE_MIN);
+ usb.setBlockable(true);
channelsList.add(usb);
NotificationChannel foregroundChannel = new NotificationChannel(
diff --git a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
index b7e68ba..51159bd 100644
--- a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
+++ b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
@@ -29,6 +29,8 @@
import android.util.DisplayMetrics;
import android.util.TypedValue;
+import org.omnirom.omnilib.utils.OmniSettings;
+
/**
* @hide
*/
@@ -73,6 +75,9 @@
r.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
false, this, UserHandle.USER_ALL);
+ r.registerContentObserver(
+ Settings.System.getUriFor(OmniSettings.OMNI_BACK_GESTURE_HEIGHT),
+ false, this, UserHandle.USER_ALL);
DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI,
runnable -> mMainHandler.post(runnable),
@@ -95,6 +100,9 @@
r.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
false, this);
+ r.registerContentObserver(
+ Settings.System.getUriFor(OmniSettings.OMNI_BACK_GESTURE_HEIGHT),
+ false, this);
DeviceConfig.addOnPropertiesChangedListener(
DeviceConfig.NAMESPACE_SYSTEMUI,
runnable -> mMainHandler.post(runnable),
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c834dde..119b734 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -173,7 +173,7 @@
void showPinningEnterExitToast(boolean entering);
void showPinningEscapeToast();
- void showShutdownUi(boolean isReboot, String reason);
+ void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom);
/**
* Used to show the authentication dialog (Biometrics, Device Credential).
@@ -390,4 +390,10 @@
* @param displayId the id of the current display.
*/
void moveFocusedTaskToDesktop(int displayId);
+
+ /**
+ *Omni
+ */
+ void toggleCameraFlash();
+ void toggleCameraFlashState(boolean enable);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 3e2f301..286ae68 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -108,7 +108,7 @@
* These methods are needed for global actions control which the UI is shown in sysui.
*/
void shutdown();
- void reboot(boolean safeMode);
+ void reboot(boolean safeMode, String reason);
/** just restarts android without rebooting device. Used for some feature flags. */
void restart();
@@ -236,4 +236,11 @@
/** Shows rear display educational dialog */
void showRearDisplayDialog(int currentBaseState);
+
+ /**
+ * Omni
+ */
+ void toggleCameraFlash();
+ void toggleCameraFlashState(boolean enable);
+ boolean getSessionStatus(int sessionType);
}
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 0eb7c4a..5a21291 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -44,6 +44,7 @@
"/sys/kernel/debug/tracing/trace_marker",
"/sys/kernel/tracing/trace_marker",
"/system/framework/framework-res.apk",
+ "/system/framework/omnirom-res.apk",
"/dev/urandom",
"/dev/ion",
"/dev/dri/renderD129", // Fixes b/31172436
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6b8056c..0b808b8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4873,6 +4873,11 @@
android:description="@string/permdesc_getPackageSize"
android:protectionLevel="normal" />
+ <!-- @hide Allows an application to change the package signature as
+ seen by applications -->
+ <permission android:name="android.permission.FAKE_PACKAGE_SIGNATURE"
+ android:protectionLevel="signature|privileged" />
+
<!-- @deprecated No longer useful, see
{@link android.content.pm.PackageManager#addPackageToPreferred}
for details. -->
diff --git a/core/res/res/values/custom_arrays.xml b/core/res/res/values/custom_arrays.xml
new file mode 100644
index 0000000..a67890b
--- /dev/null
+++ b/core/res/res/values/custom_arrays.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+** Not a Contribution.
+**
+** 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.
+*/
+-->
+<resources>
+
+ <string-array translatable="false" name="config_rebootActionsList">
+ <item>restart</item>
+ <item>reboot_recovery</item>
+ <item>reboot_bootloader</item>
+ </string-array>
+
+</resources>
diff --git a/core/res/res/values/custom_symbols.xml b/core/res/res/values/custom_symbols.xml
new file mode 100644
index 0000000..f8f3a91
--- /dev/null
+++ b/core/res/res/values/custom_symbols.xml
@@ -0,0 +1,4 @@
+<resources>
+ <java-symbol type="color" name="primary_text_material_light" />
+ <java-symbol type="color" name="primary_text_material_dark" />
+</resources>
diff --git a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
index 43cff8d..4c9b187 100644
--- a/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
+++ b/core/tests/coretests/src/com/android/internal/content/res/OverlayConfigTest.java
@@ -471,7 +471,7 @@
final OverlayConfig overlayConfig = createConfigImpl();
if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
final ArrayList<IdmapInvocation> idmapInvocations =
- overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+ overlayConfig.getImmutableFrameworkOverlayIdmapInvocations("android");
assertEquals(2, idmapInvocations.size());
final IdmapInvocation i0 = idmapInvocations.get(0);
@@ -508,7 +508,7 @@
if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
final ArrayList<IdmapInvocation> idmapInvocations =
- overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+ overlayConfig.getImmutableFrameworkOverlayIdmapInvocations("android");
assertEquals(3, idmapInvocations.size());
final IdmapInvocation i0 = idmapInvocations.get(0);
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index e618245..f4a77ec 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -63,6 +63,7 @@
static const char* kAssetsRoot = "assets";
static const char* kAppZipName = NULL; //"classes.jar";
static const char* kSystemAssets = "framework/framework-res.apk";
+static const char* kOmniRomAssets = "framework/omnirom-res.apk";
static const char* kResourceCache = "resource-cache";
static const char* kExcludeExtension = ".EXCLUDE";
@@ -367,10 +368,19 @@
const char* root = getenv("ANDROID_ROOT");
LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
- String8 path(root);
- appendPath(path, kSystemAssets);
+ bool success = true;
+ {
+ String8 path(root);
+ appendPath(path, kSystemAssets);
+ success &= addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
+ }
+ {
+ String8 path(root);
+ appendPath(path, kOmniRomAssets);
+ success &= addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
+ }
- return addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
+ return success;
}
int32_t AssetManager::nextAssetPath(const int32_t cookie) const
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index de9991a..311f3fe 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -70,6 +70,7 @@
#define IDMAP_MAGIC 0x504D4449
#define APP_PACKAGE_ID 0x7f
+#define OMNIROMSDK_PACKAGE_ID 0x3f
#define SYS_PACKAGE_ID 0x01
static const bool kDebugStringPoolNoisy = false;
@@ -5802,7 +5803,8 @@
}
uint32_t packageId = Res_GETPACKAGE(rid) + 1;
- if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID) {
+ if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID &&
+ packageId != OMNIROMSDK_PACKAGE_ID) {
outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
}
outValue->data = rid;
@@ -5823,7 +5825,8 @@
outValue->data = rid;
outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
return true;
- } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) {
+ } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID ||
+ packageId == OMNIROMSDK_PACKAGE_ID) {
// We accept packageId's generated as 0x01 in order to support
// building the android system resources
outValue->data = rid;
@@ -5969,7 +5972,8 @@
}
uint32_t packageId = Res_GETPACKAGE(rid) + 1;
- if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID) {
+ if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID &&
+ packageId != OMNIROMSDK_PACKAGE_ID) {
outValue->dataType = Res_value::TYPE_DYNAMIC_ATTRIBUTE;
}
outValue->data = rid;
@@ -5984,7 +5988,8 @@
outValue->data = rid;
outValue->dataType = Res_value::TYPE_DYNAMIC_ATTRIBUTE;
return true;
- } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) {
+ } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID ||
+ packageId == OMNIROMSDK_PACKAGE_ID) {
// We accept packageId's generated as 0x01 in order to support
// building the android system resources
outValue->data = rid;
@@ -7159,6 +7164,7 @@
// Reserved package ids
mLookupTable[APP_PACKAGE_ID] = APP_PACKAGE_ID;
mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
+ mLookupTable[OMNIROMSDK_PACKAGE_ID] = OMNIROMSDK_PACKAGE_ID;
}
status_t DynamicRefTable::load(const ResTable_lib_header* const header)
diff --git a/libs/androidfw/include/androidfw/AttributeFinder.h b/libs/androidfw/include/androidfw/AttributeFinder.h
index 03fad49..f12a964 100644
--- a/libs/androidfw/include/androidfw/AttributeFinder.h
+++ b/libs/androidfw/include/androidfw/AttributeFinder.h
@@ -74,6 +74,7 @@
// Package offsets (best-case, fast look-up).
Iterator framework_start_;
+ Iterator omnirom_framework_start_;
Iterator app_start_;
// Worst case, we have shared-library resources.
@@ -100,6 +101,9 @@
case 0x01u:
current_ = framework_start_;
break;
+ case 0x3fu:
+ current_ = omnirom_framework_start_;
+ break;
case 0x7fu:
current_ = app_start_;
break;
@@ -134,6 +138,9 @@
case 0x01u:
framework_start_ = current_;
break;
+ case 0x3fu:
+ omnirom_framework_start_ = current_;
+ break;
case 0x7fu:
app_start_ = current_;
break;
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 0f24654..b3dc6d4 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -48,6 +48,8 @@
import android.provider.MediaStore.MediaColumns;
import android.provider.Settings;
import android.provider.Settings.System;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.database.SortCursor;
@@ -149,6 +151,7 @@
* for this {@link Uri}. If showing an item for "Default" (@see
* {@link #EXTRA_RINGTONE_SHOW_DEFAULT}), this can also be one of
* {@link System#DEFAULT_RINGTONE_URI},
+ * {@link System#DEFAULT_RINGTONE2_URI},
* {@link System#DEFAULT_NOTIFICATION_URI}, or
* {@link System#DEFAULT_ALARM_ALERT_URI} to have the "Default" item
* checked.
@@ -162,7 +165,7 @@
* Given to the ringtone picker as a {@link Uri}. The {@link Uri} of the
* ringtone to play when the user attempts to preview the "Default"
* ringtone. This can be one of {@link System#DEFAULT_RINGTONE_URI},
- * {@link System#DEFAULT_NOTIFICATION_URI}, or
+ * {@link System#DEFAULT_RINGTONE2_URI}, {@link System#DEFAULT_NOTIFICATION_URI}, or
* {@link System#DEFAULT_ALARM_ALERT_URI} to have the "Default" point to
* the current sound for the given default sound type. If you are showing a
* ringtone picker for some other type of sound, you are free to provide any
@@ -201,7 +204,7 @@
* It will be one of:
* <li> the picked ringtone,
* <li> a {@link Uri} that equals {@link System#DEFAULT_RINGTONE_URI},
- * {@link System#DEFAULT_NOTIFICATION_URI}, or
+ * {@link System#DEFAULT_RINGTONE2_URI}, {@link System#DEFAULT_NOTIFICATION_URI}, or
* {@link System#DEFAULT_ALARM_ALERT_URI} if the default was chosen,
* <li> null if the "Silent" item was picked.
*
@@ -876,8 +879,8 @@
/**
* Gets the current default sound's {@link Uri}. This will give the actual
* sound {@link Uri}, instead of using this, most clients can use
- * {@link System#DEFAULT_RINGTONE_URI}.
- *
+ * {@link System#DEFAULT_RINGTONE_URI} or {@link System#DEFAULT_RINGTONE2_URI}.
+ *
* @param context A context used for querying.
* @param type The type whose default sound should be returned. One of
* {@link #TYPE_RINGTONE}, {@link #TYPE_NOTIFICATION}, or
@@ -886,7 +889,28 @@
* @see #setActualDefaultRingtoneUri(Context, int, Uri)
*/
public static Uri getActualDefaultRingtoneUri(Context context, int type) {
- String setting = getSettingForType(type);
+ return getActualDefaultRingtoneUriBySlot(context, type,
+ SubscriptionManager.getDefaultVoicePhoneId());
+ }
+
+ /**
+ * Gets the current default sound's {@link Uri} by slotId. This will give the actual
+ * sound {@link Uri}, instead of using this, most clients can use
+ * {@link System#DEFAULT_RINGTONE_URI} or {@link System#DEFAULT_RINGTONE2_URI}.
+ *
+ * @param context A context used for querying.
+ * @param type The type whose default sound should be returned. One of
+ * {@link #TYPE_RINGTONE}, {@link #TYPE_NOTIFICATION}, or
+ * {@link #TYPE_ALARM}.
+ * @param slotId The slotId whose default sound should be returned.
+ * @return A {@link Uri} pointing to the default sound for the sound type.
+ * @see #setActualDefaultRingtoneUriBySlot(Context, int, Uri, int)
+ *
+ * @hide
+ */
+
+ public static Uri getActualDefaultRingtoneUriBySlot(Context context, int type, int slotId) {
+ String setting = getSettingForTypeBySlot(type, slotId);
if (setting == null) return null;
final String uriString = Settings.System.getStringForUser(context.getContentResolver(),
setting, context.getUserId());
@@ -913,7 +937,26 @@
* @see #getActualDefaultRingtoneUri(Context, int)
*/
public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
- String setting = getSettingForType(type);
+ setActualDefaultRingtoneUriBySlot(context, type, ringtoneUri,
+ SubscriptionManager.getDefaultVoicePhoneId());
+ }
+
+ /**
+ * Sets the {@link Uri} of the default sound by slotId for a given sound type.
+ *
+ * @param context A context used for querying.
+ * @param type The type whose default sound should be set. One of
+ * {@link #TYPE_RINGTONE}, {@link #TYPE_NOTIFICATION}, or
+ * {@link #TYPE_ALARM}.
+ * @param ringtoneUri A {@link Uri} pointing to the default sound to set.
+ * @param slotId The slotId whose default sound should be set.
+ * @see #getActualDefaultRingtoneUriBySlot(Context, int, int)
+ *
+ * @hide
+ */
+ public static void setActualDefaultRingtoneUriBySlot(Context context, int type,
+ Uri ringtoneUri, int slotId) {
+ String setting = getSettingForTypeBySlot(type, slotId);
if (setting == null) return;
final ContentResolver resolver = context.getContentResolver();
@@ -1036,9 +1079,9 @@
}
}
- private static String getSettingForType(int type) {
+ private static String getSettingForTypeBySlot(int type, int slotId) {
if ((type & TYPE_RINGTONE) != 0) {
- return Settings.System.RINGTONE;
+ return slotId == 1 ? Settings.System.RINGTONE2 : Settings.System.RINGTONE;
} else if ((type & TYPE_NOTIFICATION) != 0) {
return Settings.System.NOTIFICATION_SOUND;
} else if ((type & TYPE_ALARM) != 0) {
@@ -1050,13 +1093,22 @@
/** {@hide} */
public static Uri getCacheForType(int type) {
- return getCacheForType(type, UserHandle.getCallingUserId());
+ return getCacheForTypeBySlot(type, UserHandle.getCallingUserId(),
+ SubscriptionManager.getDefaultVoicePhoneId());
}
/** {@hide} */
public static Uri getCacheForType(int type, int userId) {
+ return getCacheForTypeBySlot(type, userId, SubscriptionManager.getDefaultVoicePhoneId());
+ }
+
+ /** {@hide} */
+ public static Uri getCacheForTypeBySlot(int type, int userId, int slotId) {
if ((type & TYPE_RINGTONE) != 0) {
- return ContentProvider.maybeAddUserId(Settings.System.RINGTONE_CACHE_URI, userId);
+ Uri ringtoneUri = slotId == 1
+ ? Settings.System.RINGTONE2_CACHE_URI
+ : Settings.System.RINGTONE_CACHE_URI;
+ return ContentProvider.maybeAddUserId(ringtoneUri, userId);
} else if ((type & TYPE_NOTIFICATION) != 0) {
return ContentProvider.maybeAddUserId(Settings.System.NOTIFICATION_SOUND_CACHE_URI,
userId);
@@ -1081,6 +1133,7 @@
*
* @param defaultRingtoneUri The default {@link Uri}. For example,
* {@link System#DEFAULT_RINGTONE_URI},
+ * {@link System#DEFAULT_RINGTONE2_URI},
* {@link System#DEFAULT_NOTIFICATION_URI}, or
* {@link System#DEFAULT_ALARM_ALERT_URI}.
* @return The type of the defaultRingtoneUri, or -1.
@@ -1106,7 +1159,8 @@
}
}
- if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)) {
+ if (defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE_URI)
+ || defaultRingtoneUri.equals(Settings.System.DEFAULT_RINGTONE2_URI)) {
return TYPE_RINGTONE;
} else if (defaultRingtoneUri.equals(Settings.System.DEFAULT_NOTIFICATION_URI)) {
return TYPE_NOTIFICATION;
@@ -1122,13 +1176,31 @@
* Rather than returning the actual ringtone's sound {@link Uri}, this will
* return the symbolic {@link Uri} which will resolved to the actual sound
* when played.
- *
+ *
* @param type The ringtone type whose default should be returned.
* @return The {@link Uri} of the default ringtone for the given type.
*/
public static Uri getDefaultUri(int type) {
+ return getDefaultUriBySlot(type, SubscriptionManager.getDefaultVoicePhoneId());
+ }
+
+ /**
+ * Returns the {@link Uri} for the default ringtone by slotId of a particular type.
+ * Rather than returning the actual ringtone's sound {@link Uri}, this will
+ * return the symbolic {@link Uri} which will resolved to the actual sound
+ * when played.
+ *
+ * @param type The ringtone type whose default should be returned.
+ * @param slotId The slotId whose default should be returned.
+ * @return The {@link Uri} of the default ringtone for the given type.
+ *
+ * @hide
+ */
+ public static Uri getDefaultUriBySlot(int type, int slotId) {
if ((type & TYPE_RINGTONE) != 0) {
- return Settings.System.DEFAULT_RINGTONE_URI;
+ return slotId == 1
+ ? Settings.System.DEFAULT_RINGTONE2_URI
+ : Settings.System.DEFAULT_RINGTONE_URI;
} else if ((type & TYPE_NOTIFICATION) != 0) {
return Settings.System.DEFAULT_NOTIFICATION_URI;
} else if ((type & TYPE_ALARM) != 0) {
@@ -1242,14 +1314,20 @@
// Skip if we've already defined it at least once, so we don't
// overwrite the user changing to null
final String setting = getDefaultRingtoneSetting(type);
+ String defaultRingtone2 = Settings.System.getString(context.getContentResolver(), Settings.System.RINGTONE2);
if (Settings.System.getInt(context.getContentResolver(), setting, 0) != 0) {
- continue;
+ if (!TextUtils.isEmpty(defaultRingtone2)) {
+ continue;
+ }
}
// Try finding the scanned ringtone
Uri ringtoneUri = computeDefaultRingtoneUri(context, type);
if (ringtoneUri != null) {
RingtoneManager.setActualDefaultRingtoneUri(context, type, ringtoneUri);
+ if (TextUtils.isEmpty(defaultRingtone2)) {
+ RingtoneManager.setActualDefaultRingtoneUriBySlot(context, TYPE_RINGTONE, ringtoneUri, 1);
+ }
Settings.System.putInt(context.getContentResolver(), setting, 1);
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 5a524d9..55aed78 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -119,7 +119,7 @@
}
@Composable
- fun FooterAppVersion(showPackageName: Boolean = rememberIsDevelopmentSettingsEnabled()) {
+ fun FooterAppVersion(showPackageName: Boolean = true /*rememberIsDevelopmentSettingsEnabled()*/) {
val context = LocalContext.current
val footer =
remember(packageInfo, showPackageName) {
diff --git a/packages/SettingsLib/res/values/custom_strings.xml b/packages/SettingsLib/res/values/custom_strings.xml
new file mode 100644
index 0000000..fab17bb
--- /dev/null
+++ b/packages/SettingsLib/res/values/custom_strings.xml
@@ -0,0 +1,22 @@
+<?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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="status_deep_sleep">(Deep sleep: %1$d%2$s)</string>
+</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
index 5f72269..5816578 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
@@ -26,6 +26,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settingslib.R;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -89,7 +90,14 @@
}
private void updateTimes() {
- mUptime.setSummary(DateUtils.formatElapsedTime(SystemClock.elapsedRealtime() / 1000));
+ float deepSleepRatio = Math.max((float) (SystemClock.elapsedRealtime() - SystemClock.uptimeMillis()), 0f)
+ / SystemClock.elapsedRealtime();
+ int deepSleepPercent = Math.round(deepSleepRatio * 100);
+
+ String summary = DateUtils.formatElapsedTime(SystemClock.elapsedRealtime() / 1000) +
+ " " + mContext.getString(R.string.status_deep_sleep, deepSleepPercent, "%");
+
+ mUptime.setSummary(summary.toString());
}
private static class MyHandler extends Handler {
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
index 65d53f3..ca70a7f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
@@ -88,6 +88,41 @@
return drawable;
}
+ /**
+ * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon.
+ * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end.
+ *
+ * @param context used to get the spec for icon
+ * @param resId represents the bluetooth device drawable
+ * @param batteryLevel the battery level for bluetooth device
+ * @param iconScale the ratio of height between battery icon and bluetooth icon
+ * @param gap the gap between battery icon and bluetooth icon
+ * @param paddingSide the side padding of the battery icon
+ * @param paddingTop the top and bottom badding of the battery icon
+ */
+ public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId,
+ int batteryLevel, float iconScale, int gap, int paddingTop, int paddingSide) {
+ final Drawable deviceDrawable = context.getDrawable(resId);
+
+ final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context,
+ context.getColor(R.color.meter_background_color), batteryLevel);
+ batteryDrawable.setPadding(paddingSide, paddingTop, paddingSide, paddingTop);
+
+ final BluetoothDeviceLayerDrawable drawable = new BluetoothDeviceLayerDrawable(
+ new Drawable[]{deviceDrawable, batteryDrawable});
+ // Set the bluetooth icon at the left
+ drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.START);
+ // Set battery icon to the right of the bluetooth icon
+ drawable.setLayerInsetStart(1 /* index of batteryDrawable */,
+ deviceDrawable.getIntrinsicWidth() + gap);
+ drawable.setLayerInsetTop(1 /* index of batteryDrawable */,
+ (int) (deviceDrawable.getIntrinsicHeight() * (1 - iconScale)));
+
+ drawable.setConstantState(context, resId, batteryLevel, iconScale);
+
+ return drawable;
+ }
+
public void setConstantState(Context context, int resId, int batteryLevel, float iconScale) {
mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel, iconScale);
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 00ae05c..2bbe882 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -40,6 +40,7 @@
"device_config_service_flags_java",
"libaconfig_java_proto_lite",
"notification_flags_lib",
+ "OmniLib",
"SettingsLibDeviceStateRotationLock",
"SettingsLibDisplayUtils",
],
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
index 255b1ad..4c281f0 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
@@ -35,6 +35,15 @@
*/
public class SettingsValidators {
+ public static final Validator OMNI_CHARGING_CONTROL_LIMIT_VALIDATOR =
+ new InclusiveIntegerRangeValidator(70, 100);
+
+ public static final Validator OMNI_CHARGING_CONTROL_MODE_VALIDATOR =
+ new InclusiveIntegerRangeValidator(1, 3);
+
+ public static final Validator OMNI_CHARGING_CONTROL_TIME_VALIDATOR =
+ new InclusiveIntegerRangeValidator(0, 86400);
+
public static final Validator BOOLEAN_VALIDATOR =
new DiscreteValueValidator(new String[] {"0", "1"});
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 326bff4..daf25a4e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -45,6 +45,7 @@
import android.provider.settings.backup.SystemSettings;
import android.provider.settings.validators.GlobalSettingsValidators;
import android.provider.settings.validators.SecureSettingsValidators;
+import android.provider.settings.validators.SettingsValidators;
import android.provider.settings.validators.SystemSettingsValidators;
import android.provider.settings.validators.Validator;
import android.telephony.SubscriptionManager;
@@ -62,6 +63,8 @@
import com.android.settingslib.display.DisplayDensityConfiguration;
import com.android.window.flags.Flags;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -715,7 +718,9 @@
Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null,
null, null);
try {
- return extractRelevantValues(cursor, SystemSettings.SETTINGS_TO_BACKUP, KEY_SYSTEM);
+ String[] settings = ArrayUtils.concat(String.class, SystemSettings.SETTINGS_TO_BACKUP,
+ OmniSettings.OMNI_SETTINGS_TO_BACKUP, KEY_SYSTEM);
+ return extractRelevantValues(cursor, settings);
} finally {
cursor.close();
}
@@ -1101,8 +1106,32 @@
validators = SecureSettingsValidators.VALIDATORS;
} else if (contentUri.equals(Settings.System.CONTENT_URI)) {
allowlist = ArrayUtils.concat(String.class, SystemSettings.SETTINGS_TO_BACKUP,
- Settings.System.LEGACY_RESTORE_SETTINGS);
+ Settings.System.LEGACY_RESTORE_SETTINGS, OmniSettings.OMNI_SETTINGS_TO_BACKUP);
validators = SystemSettingsValidators.VALIDATORS;
+
+ final Map<String, Integer> omniValidators = OmniSettings.OMNI_SETTINGS_VALIDATORS;
+ // BOOLEAN_VALIDATOR == 0
+ // ANY_INTEGER_VALIDATOR == 1
+ // ANY_STRING_VALIDATOR == 2
+ // OMNI_CHARGING_CONTROL_LIMIT_VALIDATOR == 3 +++InclusiveIntegerRangeValidator
+ // OMNI_CHARGING_CONTROL_MODE_VALIDATOR == 4
+ // OMNI_CHARGING_CONTROL_TIME_VALIDATOR == 5 ---InclusiveIntegerRangeValidator
+ for (String key : omniValidators.keySet()) {
+ Integer validatorId = omniValidators.get(key);
+ if (validatorId == 0) {
+ validators.put(key, SettingsValidators.BOOLEAN_VALIDATOR);
+ } else if (validatorId == 1) {
+ validators.put(key, SettingsValidators.ANY_INTEGER_VALIDATOR);
+ } else if (validatorId == 2) {
+ validators.put(key, SettingsValidators.ANY_STRING_VALIDATOR);
+ } else if (validatorId == 3) {
+ validators.put(key, SettingsValidators.OMNI_CHARGING_CONTROL_LIMIT_VALIDATOR);
+ } else if (validatorId == 4) {
+ validators.put(key, SettingsValidators.OMNI_CHARGING_CONTROL_MODE_VALIDATOR);
+ } else if (validatorId == 5) {
+ validators.put(key, SettingsValidators.OMNI_CHARGING_CONTROL_TIME_VALIDATOR);
+ }
+ }
} else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
allowlist = ArrayUtils.concat(String.class, getGlobalSettingsToBackup(),
Settings.Global.LEGACY_RESTORE_SETTINGS);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index ea8ae7b..2b93f16 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -207,6 +207,7 @@
} else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
return;
} else if (Settings.System.RINGTONE.equals(name)
+ || Settings.System.RINGTONE2.equals(name)
|| Settings.System.NOTIFICATION_SOUND.equals(name)
|| Settings.System.ALARM_ALERT.equals(name)) {
setRingtone(name, value);
@@ -291,11 +292,12 @@
public String onBackupValue(String name, String value) {
// Special processing for backing up ringtones & notification sounds
- if (Settings.System.RINGTONE.equals(name)
+ if (Settings.System.RINGTONE.equals(name) || Settings.System.RINGTONE2.equals(name)
|| Settings.System.NOTIFICATION_SOUND.equals(name)
|| Settings.System.ALARM_ALERT.equals(name)) {
if (value == null) {
- if (Settings.System.RINGTONE.equals(name)) {
+ if (Settings.System.RINGTONE.equals(name)
+ || Settings.System.RINGTONE2.equals(name)) {
// For ringtones, we need to distinguish between non-telephony vs telephony
if (mTelephonyManager != null && mTelephonyManager.isVoiceCapable()) {
// Backup a null ringtone as silent on voice-capable devices
@@ -352,7 +354,7 @@
/**
* Sets the ringtone of type specified by the name.
*
- * @param name should be Settings.System.RINGTONE, Settings.System.NOTIFICATION_SOUND
+ * @param name should be Settings.System.RINGTONE, Settings.System.RINGTONE2, Settings.System.NOTIFICATION_SOUND
* or Settings.System.ALARM_ALERT.
* @param value can be a canonicalized uri or "_silent" to indicate a silent (null) ringtone.
*/
@@ -397,6 +399,8 @@
switch (name) {
case Settings.System.RINGTONE:
return RingtoneManager.TYPE_RINGTONE;
+ case Settings.System.RINGTONE2:
+ return RingtoneManager.TYPE_RINGTONE;
case Settings.System.NOTIFICATION_SOUND:
return RingtoneManager.TYPE_NOTIFICATION;
case Settings.System.ALARM_ALERT:
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 37eda3e..c6e8ac1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2934,8 +2934,14 @@
Settings.System.RINGTONE,
SystemSettingsProto.Ringtone.DEFAULT_URI);
dumpSetting(s, p,
+ Settings.System.RINGTONE2,
+ SystemSettingsProto.Ringtone.DEFAULT_URI);
+ dumpSetting(s, p,
Settings.System.RINGTONE_CACHE,
SystemSettingsProto.Ringtone.CACHE);
+ dumpSetting(s, p,
+ Settings.System.RINGTONE2_CACHE,
+ SystemSettingsProto.Ringtone.CACHE);
p.end(ringtoneToken);
final long rotationToken = p.start(SystemSettingsProto.ROTATION);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6128d45..b60e18c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -821,6 +821,8 @@
final String cacheRingtoneSetting;
if (Settings.System.RINGTONE_CACHE_URI.equals(uri)) {
cacheRingtoneSetting = Settings.System.RINGTONE;
+ } else if (Settings.System.RINGTONE2_CACHE_URI.equals(uri)) {
+ cacheRingtoneSetting = Settings.System.RINGTONE2;
} else if (Settings.System.NOTIFICATION_SOUND_CACHE_URI.equals(uri)) {
cacheRingtoneSetting = Settings.System.NOTIFICATION_SOUND;
} else if (Settings.System.ALARM_ALERT_CACHE_URI.equals(uri)) {
@@ -838,6 +840,8 @@
private String getCacheName(String setting) {
if (Settings.System.RINGTONE.equals(setting)) {
return Settings.System.RINGTONE_CACHE;
+ } else if (Settings.System.RINGTONE2.equals(setting)) {
+ return Settings.System.RINGTONE2_CACHE;
} else if (Settings.System.NOTIFICATION_SOUND.equals(setting)) {
return Settings.System.NOTIFICATION_SOUND_CACHE;
} else if (Settings.System.ALARM_ALERT.equals(setting)) {
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 3d250fd..ec18a77 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -512,6 +512,7 @@
"androidx.activity_activity-compose",
"androidx.compose.animation_animation-graphics",
"androidx.lifecycle_lifecycle-viewmodel-compose",
+ "OmniLib",
],
libs: [
"keepanno-annotations",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 11cb070..a3eaeb3 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -394,6 +394,9 @@
<protected-broadcast android:name="com.android.systemui.action.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG" />
<protected-broadcast android:name="com.android.systemui.STARTED" />
+ <!-- OmniJaws -->
+ <uses-permission android:name="org.omnirom.omnijaws.READ_WEATHER" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
@@ -572,6 +575,10 @@
</intent-filter>
</activity-alias>
+ <!-- Callback for deleting screenshot notification -->
+ <receiver android:name=".screenshot.DeleteScreenshotReceiver"
+ android:exported="false" />
+
<!-- Callback for invoking a smart action from the screenshot notification. -->
<receiver android:name=".screenshot.SmartActionsReceiver"
android:exported="false"/>
@@ -1154,5 +1161,9 @@
android:exported="false"
/>
+ <!-- omni additions start -->
+ <service android:name=".omni.CPUInfoService"
+ android:exported="false" />
+
</application>
</manifest>
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index ad9eba8..2079bf4 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -18,6 +18,7 @@
import android.graphics.Color
import android.graphics.Rect
import android.icu.text.NumberFormat
+import android.provider.Settings.System
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
@@ -40,6 +41,7 @@
import com.android.systemui.plugins.clocks.ThemeConfig
import com.android.systemui.plugins.clocks.WeatherData
import com.android.systemui.plugins.clocks.ZenData
+import org.omnirom.omnilib.utils.OmniSettings
import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
@@ -146,12 +148,21 @@
override fun onThemeChanged(theme: ThemeConfig) {
this@DefaultClockFaceController.theme = theme
+ val coloredClock = System.getInt(ctx.getContentResolver(),
+ OmniSettings.OMNI_LOCKSCREEN_CLOCK_COLORED, 1) != 0
val color =
when {
theme.seedColor != null -> theme.seedColor!!
theme.isDarkTheme ->
- resources.getColor(android.R.color.system_accent1_100)
- else -> resources.getColor(android.R.color.system_accent2_600)
+ if (coloredClock)
+ resources.getColor(android.R.color.system_accent1_100)
+ else
+ resources.getColor(com.android.internal.R.color.primary_text_material_dark)
+ else ->
+ if (coloredClock)
+ resources.getColor(android.R.color.system_accent2_600)
+ else
+ resources.getColor(com.android.internal.R.color.primary_text_material_light)
}
if (currentColor == color) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
index 95ff13b..7775551 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
@@ -26,7 +26,7 @@
int VERSION = 1;
void showGlobalActions(GlobalActionsManager manager);
- default void showShutdownUi(boolean isReboot, String reason) {
+ default void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
}
default void destroy() {
@@ -40,6 +40,6 @@
void onGlobalActionsHidden();
void shutdown();
- void reboot(boolean safeMode);
+ void reboot(boolean safeMode, String reason);
}
}
diff --git a/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big_dim.xml b/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big_dim.xml
new file mode 100644
index 0000000..eaada7a
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/ic_access_alarms_big_dim.xml
@@ -0,0 +1,25 @@
+<!--
+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="18dp"
+ android:height="18dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:fillAlpha="0.3"
+ android:pathData="M21.35,6.49c-0.35,0.42 -0.98,0.47 -1.4,0.12l-3.07,-2.57a1,1 0,1 1,1.29 -1.53l3.07,2.57c0.42,0.35 0.47,0.98 0.11,1.41zM7.24,2.63a1,1 0,0 0,-1.41 -0.13L2.77,5.07A0.996,0.996 0,1 0,4.05 6.6l3.06,-2.57c0.43,-0.35 0.48,-0.98 0.13,-1.4zM11.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v4.68c0,0.35 0.18,0.68 0.49,0.86l3.65,2.19c0.34,0.2 0.78,0.1 0.98,-0.24a0.71,0.71 0,0 0,-0.25 -0.99l-3.37,-2v-4.5c0,-0.41 -0.34,-0.75 -0.75,-0.75zM12,5.9c-3.91,0 -7.1,3.18 -7.1,7.1s3.19,7.1 7.1,7.1 7.1,-3.18 7.1,-7.1 -3.19,-7.1 -7.1,-7.1M12,4a9,9 0,1 1,-0.001 18.001A9,9 0,0 1,12 4z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png b/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png
new file mode 100644
index 0000000..4102e28
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
index ec15b10..31643e2 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
@@ -19,15 +19,11 @@
android:paddingMode="stack" >
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
- <inset
- android:insetLeft="@dimen/rounded_slider_track_inset"
- android:insetRight="@dimen/rounded_slider_track_inset" >
- <shape>
- <size android:height="@dimen/rounded_slider_track_width" />
- <corners android:radius="@dimen/rounded_slider_track_corner_radius" />
- <solid android:color="?androidprv:attr/customColorShadeInactive" />
- </shape>
- </inset>
+ <shape>
+ <size android:height="@dimen/rounded_slider_track_width" />
+ <corners android:radius="@dimen/rounded_slider_track_corner_radius" />
+ <solid android:color="?androidprv:attr/customColorShadeInactive" />
+ </shape>
</item>
<item android:id="@android:id/progress"
android:gravity="center_vertical|fill_horizontal">
diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
index a9e7adf..03b470a 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml
@@ -19,11 +19,11 @@
xmlns:priv-android="http://schemas.android.com/apk/prv/res/android"
android:autoMirrored="true">
<item android:id="@+id/slider_foreground"
- android:height="@dimen/rounded_slider_height">
+ android:gravity="center_vertical|fill_horizontal">
<shape>
- <size android:height="@dimen/rounded_slider_height" />
+ <size android:height="@dimen/rounded_slider_progress_width" />
<solid android:color="?attr/shadeActive" />
- <corners android:radius="@dimen/rounded_slider_corner_radius"/>
+ <corners android:radius="@dimen/rounded_slider_progress_corner_radius"/>
</shape>
</item>
<item>
@@ -33,15 +33,4 @@
<solid android:color="@color/brightness_slider_overlay_color" />
</shape>
</item>
- <item
- android:id="@+id/slider_icon"
- android:gravity="center_vertical|right"
- android:height="@dimen/rounded_slider_icon_size"
- android:width="@dimen/rounded_slider_icon_size"
- android:right="@dimen/rounded_slider_icon_inset">
- <com.android.systemui.util.AlphaTintDrawableWrapper
- android:drawable="@drawable/ic_brightness"
- android:tint="?attr/onShadeActive"
- />
- </item>
</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/brightness_progress_thumb.xml b/packages/SystemUI/res/drawable/brightness_progress_thumb.xml
new file mode 100644
index 0000000..0e37987
--- /dev/null
+++ b/packages/SystemUI/res/drawable/brightness_progress_thumb.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:priv-android="http://schemas.android.com/apk/prv/res/android"
+ android:autoMirrored="true">
+ <item
+ android:width="@dimen/rounded_slider_height"
+ android:height="@dimen/rounded_slider_height">
+ <shape>
+ <size android:height="@dimen/rounded_slider_height" />
+ <solid android:color="?priv-android:attr/colorAccentPrimary" />
+ <corners android:radius="@dimen/rounded_slider_corner_radius" />
+ </shape>
+ </item>
+ <item
+ android:id="@+id/slider_icon"
+ android:width="@dimen/rounded_slider_icon_size"
+ android:height="@dimen/rounded_slider_icon_size"
+ android:gravity="center">
+ <com.android.systemui.util.AlphaTintDrawableWrapper
+ android:drawable="@drawable/ic_brightness"
+ android:tint="?android:attr/textColorPrimaryInverse" />
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_navbar_chevron_left.xml b/packages/SystemUI/res/drawable/ic_navbar_chevron_left.xml
new file mode 100644
index 0000000..c6329f0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_navbar_chevron_left.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?attr/singleToneColor"
+ android:pathData="M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_navbar_chevron_right.xml b/packages/SystemUI/res/drawable/ic_navbar_chevron_right.xml
new file mode 100644
index 0000000..86d20cb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_navbar_chevron_right.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ 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:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?attr/singleToneColor"
+ android:pathData="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_aod.xml b/packages/SystemUI/res/drawable/ic_qs_aod.xml
new file mode 100644
index 0000000..4bb2d4a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_aod.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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="M17,19 L17,5 L7,5 L7,19 L17,19 M17,1 C18.1046,1,19,1.89543,19,3 L19,21 C19,22.1046,18.1046,23,17,23 L7,23 C5.89,23,5,22.1,5,21 L5,3 C5,1.89,5.89,1,7,1 L17,1 M9,7 L15,7 L15,9 L9,9 L9,7" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_caffeine.xml b/packages/SystemUI/res/drawable/ic_qs_caffeine.xml
new file mode 100644
index 0000000..2c3ba97
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_caffeine.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015 The CyanogenMod Project
+ Copyright (c) 2017 The LineageOS 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="48dp"
+ android:height="48dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M2,21H20V19H2M20,8H18V5H20M20,3H4V13A4,4 0 0,0 8,17H14A4,4 0 0,0 18,13V10H20A2,2 0 0,0 22,8V5C22,3.89 21.1,3 20,3Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_switch_0.xml b/packages/SystemUI/res/drawable/ic_qs_data_switch_0.xml
new file mode 100644
index 0000000..81b58ab
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_data_switch_0.xml
@@ -0,0 +1,4 @@
+<vector android:height="48dp" android:viewportHeight="24"
+ android:viewportWidth="24" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffffff" android:pathData="M19.99,4c0,-1.1 -0.89,-2 -1.99,-2h-7.17c-0.53,0 -1.04,0.21 -1.42,0.59L4.59,7.41C4.21,7.79 4,8.3 4,8.83L4,20c0,1.1 0.9,2 2,2h12.01c1.1,0 1.99,-0.9 1.99,-2l-0.01,-16zM8,19c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM16,19c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM8,15c-0.55,0 -1,-0.45 -1,-1v-2c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v2c0,0.55 -0.45,1 -1,1zM12,19c-0.55,0 -1,-0.45 -1,-1v-2c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v2c0,0.55 -0.45,1 -1,1zM12,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM16,15c-0.55,0 -1,-0.45 -1,-1v-2c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v2c0,0.55 -0.45,1 -1,1z" android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_switch_1.xml b/packages/SystemUI/res/drawable/ic_qs_data_switch_1.xml
new file mode 100644
index 0000000..1747678
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_data_switch_1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:aapt="http://schemas.android.com/aapt" android:height="48dp" android:width="48dp" android:viewportWidth="72" android:viewportHeight="72">
+ <path android:fillColor="#ffffffff" android:pathData="m36,66 l-18,0c-3.3,0 -6,-2.7 -6,-6L12,24 30,6 54,6c3.3,0 5.97,2.7 5.97,6l0.02,33 -20.99,0C37.35,45 36,46.34 36,47.99zM42,28 L48,35 54,28zM54,19 L48,12 42,19zM51.32,66 L47.36,66 47.36,53.39 43.47,54.53 43.47,51.53 50.96,48.94 51.32,48.94z" android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_switch_2.xml b/packages/SystemUI/res/drawable/ic_qs_data_switch_2.xml
new file mode 100644
index 0000000..438fc94
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_data_switch_2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:aapt="http://schemas.android.com/aapt" android:height="48dp" android:width="48dp" android:viewportWidth="72" android:viewportHeight="72">
+ <path android:fillColor="#ffffffff" android:pathData="m36,66 l-18,0c-3.3,0 -6,-2.7 -6,-6L12,24 30,6 54,6c3.3,0 5.97,2.7 5.97,6l0.02,33 -20.99,0C37.35,45 36,46.34 36,47.99zM42,28 L48,35 54,28zM48,12 L42,19 54,19zM54.48,66 L42.57,66 42.57,63.42 48.06,57.66c0.73,-0.83 1.25,-1.54 1.56,-2.13 0.31,-0.59 0.47,-1.1 0.47,-1.54 0,-0.73 -0.16,-1.29 -0.48,-1.68 -0.32,-0.38 -0.79,-0.57 -1.39,-0.57 -0.3,0 -0.58,0.07 -0.83,0.21 -0.25,0.14 -0.46,0.33 -0.64,0.57 -0.18,0.24 -0.31,0.53 -0.41,0.85 -0.1,0.32 -0.15,0.68 -0.15,1.06l-3.96,0c0,-0.78 0.15,-1.52 0.44,-2.21 0.29,-0.7 0.71,-1.3 1.24,-1.83 0.54,-0.52 1.18,-0.94 1.92,-1.24 0.75,-0.3 1.57,-0.45 2.48,-0.45 0.95,0 1.78,0.11 2.49,0.33 0.71,0.22 1.31,0.54 1.8,0.97 0.48,0.42 0.85,0.94 1.1,1.55 0.25,0.61 0.37,1.31 0.37,2.09 0,0.59 -0.09,1.16 -0.28,1.71 -0.19,0.54 -0.46,1.08 -0.81,1.62 -0.35,0.54 -0.78,1.09 -1.29,1.65 -0.51,0.56 -1.08,1.16 -1.71,1.79l-2.2,2.54 6.71,0z" android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_restart_bootloader.xml b/packages/SystemUI/res/drawable/ic_restart_bootloader.xml
new file mode 100644
index 0000000..6029f4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_restart_bootloader.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal" >
+
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12.6329,4.07972 C17.2364,4.07972,20.9658,7.82577,20.9658,12.4043
+C20.9658,16.9828,17.2364,20.7288,12.6329,20.7288
+C9.71098,20.7288,7.15535,19.2137,5.66525,16.9245 L6.98053,15.8839
+C8.15429,17.7902,10.2438,19.0639,12.6412,19.0639
+C16.3192,19.0639,19.3008,16.0823,19.3008,12.4043
+C19.3008,8.72628,16.3192,5.74466,12.6412,5.74466
+C9.24478,5.74466,6.44774,8.29197,6.03983,11.5718 L8.33741,11.5718
+L5.22403,14.6769 L2.11897,11.5718 L4.35827,11.5718
+C4.77451,7.36791,8.32077,4.07972,12.6329,4.07972 M15.097,10.9391
+C15.5132,10.9474,15.8545,11.2804,15.8545,11.705 L15.8545,15.5426
+C15.8545,15.9588,15.5132,16.3085,15.0886,16.3085 L10.4851,16.3085
+C10.0605,16.3085,9.71924,15.9589,9.71924,15.5426 L9.71924,11.705
+C9.71924,11.2804,10.0605,10.9475,10.4768,10.9391 M10.4768,10.9391
+L10.4768,10.0983 M10.4768,10.0983 C10.4768,8.82464,11.5174,7.7924,12.7827,7.7924
+C14.0564,7.7924,15.0969,8.82464,15.0969,10.0983 M15.0969,10.0983
+L15.0969,10.9391 M11.6422,10.0983 L11.6422,10.9391 M11.6422,10.9391
+L13.9315,10.9391 M13.9315,10.9391 L13.9315,10.0983 M13.9315,10.0983
+C13.9315,9.46563,13.4154,8.95784,12.7827,8.95784
+C12.1584,8.95784,11.6422,9.46564,11.6422,10.0983" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_restart_fastboot.xml b/packages/SystemUI/res/drawable/ic_restart_fastboot.xml
new file mode 100644
index 0000000..495c618
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_restart_fastboot.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal" >
+
+ <path android:fillColor="#000" android:pathData="M18,18.5A1.5,1.5 0 0,0 19.5,17A1.5,1.5 0 0,0 18,15.5A1.5,1.5 0 0,0 16.5,17A1.5,1.5 0 0,0 18,18.5M19.5,9.5H17V12H21.46L19.5,9.5M6,18.5A1.5,1.5 0 0,0 7.5,17A1.5,1.5 0 0,0 6,15.5A1.5,1.5 0 0,0 4.5,17A1.5,1.5 0 0,0 6,18.5M20,8L23,12V17H21A3,3 0 0,1 18,20A3,3 0 0,1 15,17H9A3,3 0 0,1 6,20A3,3 0 0,1 3,17H1V6C1,4.89 1.89,4 3,4H17V8H20M8,6V9H5V11H8V14H10V11H13V9H10V6H8Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_restart_recovery.xml b/packages/SystemUI/res/drawable/ic_restart_recovery.xml
new file mode 100644
index 0000000..ee3cd17
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_restart_recovery.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal" >
+
+ <path
+ android:fillColor="#FF000000"
+ android:strokeWidth="1"
+ android:pathData="M12.6123,18.971 L12.6123,17.1438 L13.7308,17.1438
+C14.346,17.1438,14.8925,17.1274,14.9453,17.1073
+C14.9981,17.0872,15.0414,17.0192,15.0414,16.9561
+C15.0414,16.893,13.9977,15.529,12.722,13.9249
+C10.7629,11.4614,10.3813,11.0111,10.2655,11.0263
+C10.1642,11.0395,9.56144,11.783,7.96108,13.8686
+C5.49619,17.0809,5.60376,16.9327,5.65048,17.0531
+C5.68017,17.1297,5.87403,17.1437,6.90206,17.1437 L8.11851,17.1437
+L8.11851,18.5259 C8.11851,19.2861,8.10278,19.9081,8.08356,19.9081
+C8.01872,19.9081,7.18025,19.4101,6.78251,19.1353
+C6.20418,18.7359,5.04692,17.5583,4.64819,16.9635
+C3.95753,15.9333,3.51884,14.8937,3.25353,13.6583
+C3.05947,12.7547,3.05947,11.1966,3.25353,10.293
+C3.64609,8.46515,4.42025,7.04017,5.7189,5.75504
+C7.0163,4.47116,8.49362,3.68495,10.2838,3.32565
+C10.6231,3.25757,11.0125,3.20186,11.1492,3.20186 L11.3977,3.20186
+L11.3977,5.0335 L11.3977,6.86514 L10.168,6.88141
+C8.98219,6.8971,8.93839,6.90198,8.94149,7.01811
+C8.94599,7.18646,13.5756,12.9973,13.7053,12.9973
+C13.8372,12.9973,18.3206,7.16517,18.3206,6.9936
+C18.3206,6.87365,18.2856,6.86968,17.0909,6.85388 L15.8612,6.83761
+L15.8449,5.44041 C15.8359,4.67195,15.8437,4.04321,15.8621,4.04321
+C15.8805,4.04321,16.0382,4.11436,16.2124,4.20132
+C16.8508,4.51994,17.6363,5.10703,18.2911,5.75507
+C19.5898,7.04019,20.3639,8.46518,20.7565,10.293
+C20.8673,10.8087,20.892,11.1162,20.892,11.9756
+C20.892,12.8351,20.8672,13.1426,20.7565,13.6582
+C20.3585,15.5114,19.6077,16.8933,18.2911,18.1962
+C16.7779,19.6937,15.0196,20.5282,12.8703,20.7691 L12.6122,20.798
+L12.6122,18.9708 Z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
index d7a9edc..45efa41 100644
--- a/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
+++ b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="?android:attr/colorBackground"/>
- <corners android:topLeftRadius="20dp"
- android:topRightRadius="20dp" />
+ <corners android:topLeftRadius="?android:attr/dialogCornerRadius"
+ android:topRightRadius="?android:attr/dialogCornerRadius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar.xml b/packages/SystemUI/res/drawable/volume_row_seekbar.xml
index d7d75d4..b0c8189 100644
--- a/packages/SystemUI/res/drawable/volume_row_seekbar.xml
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar.xml
@@ -23,11 +23,15 @@
<!-- The groove used for indicating max volume !-->
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
- <shape>
- <size android:height="@dimen/volume_dialog_track_width" />
- <corners android:radius="@dimen/volume_dialog_panel_width_half" />
- <solid android:color="?androidprv:attr/materialColorOutlineVariant" />
- </shape>
+ <inset
+ android:insetLeft="@dimen/rounded_slider_track_negative_inset"
+ android:insetRight="@dimen/rounded_slider_track_negative_inset" >
+ <shape>
+ <size android:height="@dimen/volume_dialog_track_width" />
+ <corners android:radius="@dimen/volume_dialog_panel_width_half" />
+ <solid android:color="?androidprv:attr/materialColorOutlineVariant" />
+ </shape>
+ </inset>
</item>
<item android:id="@android:id/progress"
android:gravity="center_vertical|fill_horizontal">
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
index fa06bd6..3cef748 100644
--- a/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar_progress.xml
@@ -22,24 +22,9 @@
android:autoMirrored="true">
<item android:id="@+id/volume_seekbar_progress_solid">
<shape>
- <size android:height="@dimen/volume_dialog_slider_width_legacy" />
+ <size android:height="@dimen/volume_seekbar_progress_width" />
<solid android:color="?android:attr/colorAccent" />
- <corners android:radius="@dimen/volume_dialog_slider_corner_radius"/>
+ <corners android:radius="@dimen/volume_seekbar_progress_corner_radius"/>
</shape>
</item>
- <item
- android:id="@+id/volume_seekbar_progress_icon"
- android:gravity="center_vertical|right"
- android:height="@dimen/rounded_slider_icon_size"
- android:width="@dimen/rounded_slider_icon_size"
- android:right="@dimen/volume_slider_icon_inset">
- <rotate
- android:fromDegrees="-270"
- android:toDegrees="-270">
- <!-- A placeholder drawable is required here - it'll be replaced in code. -->
- <com.android.systemui.util.AlphaTintDrawableWrapper
- android:drawable="@drawable/ic_volume_media"
- android:tint="?androidprv:attr/colorAccentPrimaryVariant" />
- </rotate>
- </item>
</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/volume_row_seekbar_thumb.xml b/packages/SystemUI/res/drawable/volume_row_seekbar_thumb.xml
new file mode 100644
index 0000000..2abd3f4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/volume_row_seekbar_thumb.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+
+<!-- Progress drawable for volume row SeekBars. This is the accent-colored round rect that moves up
+ and down as the progress value changes. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:autoMirrored="true">
+ <item
+ android:width="@dimen/volume_dialog_slider_width"
+ android:height="@dimen/volume_dialog_slider_width">
+ <shape>
+ <size android:height="@dimen/volume_dialog_slider_width" />
+ <solid android:color="?android:attr/colorAccent" />
+ <corners android:radius="@dimen/volume_dialog_slider_corner_radius"/>
+ </shape>
+ </item>
+ <item
+ android:id="@+id/volume_seekbar_progress_icon"
+ android:height="@dimen/rounded_slider_icon_size"
+ android:width="@dimen/rounded_slider_icon_size"
+ android:gravity="center">
+ <rotate
+ android:fromDegrees="-270"
+ android:toDegrees="-270">
+ <!-- A placeholder drawable is required here - it'll be replaced in code. -->
+ <com.android.systemui.util.AlphaTintDrawableWrapper
+ android:drawable="@drawable/ic_volume_media"
+ android:tint="?androidprv:attr/colorAccentPrimaryVariant" />
+ </rotate>
+ </item>
+</layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml b/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
index e1ee06d..ccf629f 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml
@@ -29,7 +29,7 @@
android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
android:padding="@dimen/global_actions_button_padding"
android:scaleType="centerInside"
- android:tint="@color/global_actions_lite_text"
+ android:tint="@color/global_actions_lite_icon"
android:background="@drawable/global_actions_lite_button"/>
<TextView
android:id="@*android:id/message"
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
index c9d3f98..b7fb374 100644
--- a/packages/SystemUI/res/layout/home_handle.xml
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -19,8 +19,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/home_handle"
android:layout_width="@dimen/navigation_home_handle_width"
- android:layout_height="match_parent"
+ android:layout_height="@dimen/navigation_home_handle_height"
android:layout_weight="0"
+ android:layout_gravity="bottom"
android:contentDescription="@string/accessibility_home"
android:paddingStart="@dimen/navigation_key_padding"
android:paddingEnd="@dimen/navigation_key_padding"
diff --git a/packages/SystemUI/res/layout/home_handle_small.xml b/packages/SystemUI/res/layout/home_handle_small.xml
new file mode 100644
index 0000000..d9fc55a
--- /dev/null
+++ b/packages/SystemUI/res/layout/home_handle_small.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<com.android.systemui.navigationbar.gestural.NavigationHandle
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/home_handle"
+ android:layout_width="@dimen/navigation_home_handle_small_width"
+ android:layout_height="@dimen/navigation_home_handle_height"
+ android:layout_weight="0"
+ android:layout_gravity="bottom"
+ android:contentDescription="@string/accessibility_home"
+ android:paddingStart="@dimen/navigation_key_padding"
+ android:paddingEnd="@dimen/navigation_key_padding"
+ />
+
diff --git a/packages/SystemUI/res/layout/nav_buttons_dpad_group.xml b/packages/SystemUI/res/layout/nav_buttons_dpad_group.xml
new file mode 100644
index 0000000..6afc9de
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_buttons_dpad_group.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/dpad_group"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:clipChildren="false">
+
+ <com.android.systemui.navigationbar.views.buttons.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ systemui:keyCode="21"
+ android:visibility="gone"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_dpad_left" />
+
+ <com.android.systemui.navigationbar.views.buttons.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ systemui:keyCode="22"
+ android:visibility="gone"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_dpad_right" />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/nav_buttons_dpad_group_vertical.xml b/packages/SystemUI/res/layout/nav_buttons_dpad_group_vertical.xml
new file mode 100644
index 0000000..7139368
--- /dev/null
+++ b/packages/SystemUI/res/layout/nav_buttons_dpad_group_vertical.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/dpad_group"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:clipChildren="false">
+
+ <com.android.systemui.navigationbar.views.buttons.KeyButtonView
+ android:id="@+id/dpad_left"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/navigation_extra_key_width"
+ android:layout_alignParentTop="true"
+ systemui:keyCode="21"
+ android:visibility="gone"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_dpad_left" />
+
+ <com.android.systemui.navigationbar.views.buttons.KeyButtonView
+ android:id="@+id/dpad_right"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/navigation_extra_key_width"
+ android:layout_alignParentBottom="true"
+ systemui:keyCode="22"
+ android:visibility="gone"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_dpad_right" />
+
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index 5c6c9a4..fb79645 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -53,6 +53,8 @@
android:clipToPadding="false"
android:clipChildren="false" />
+ <include layout="@layout/nav_buttons_dpad_group" />
+
</com.android.systemui.navigationbar.views.buttons.NearestTouchFrame>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_layout_vertical.xml b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
index c64e3f7..773de3c 100644
--- a/packages/SystemUI/res/layout/navigation_layout_vertical.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
@@ -50,6 +50,8 @@
android:clipToPadding="false"
android:clipChildren="false" />
+ <include layout="@layout/nav_buttons_dpad_group_vertical" />
+
</com.android.systemui.navigationbar.views.buttons.NearestTouchFrame>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/qs_tile_label_vertical.xml b/packages/SystemUI/res/layout/qs_tile_label_vertical.xml
new file mode 100644
index 0000000..de2eae3
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_label_vertical.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+<com.android.systemui.qs.tileimpl.IgnorableChildLinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:orientation="vertical"
+ android:layout_gravity="center_horizontal">
+
+ <TextView
+ android:id="@+id/tile_label"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:textDirection="locale"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="1"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"/>
+
+ <TextView
+ android:id="@+id/app_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textDirection="locale"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="1"
+ android:singleLine="true"
+ android:visibility="gone"
+ android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary"
+ android:textColor="?attr/onShadeInactive"/>
+
+</com.android.systemui.qs.tileimpl.IgnorableChildLinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 62ceb07..571b5a9 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -30,9 +30,9 @@
android:layout_height="@dimen/brightness_mirror_height"
android:layout_gravity="center_vertical"
android:minHeight="48dp"
- android:thumb="@null"
- android:paddingStart="0dp"
- android:paddingEnd="0dp"
+ android:thumb="@drawable/brightness_progress_thumb"
+ android:paddingStart="@dimen/brightness_progress_padding"
+ android:paddingEnd="@dimen/brightness_progress_padding"
android:progressDrawable="@drawable/brightness_progress_drawable"
android:splitTrack="false"
/>
diff --git a/packages/SystemUI/res/layout/udfps_touch_overlay.xml b/packages/SystemUI/res/layout/udfps_touch_overlay.xml
index 498d59b..687f404 100644
--- a/packages/SystemUI/res/layout/udfps_touch_overlay.xml
+++ b/packages/SystemUI/res/layout/udfps_touch_overlay.xml
@@ -18,4 +18,9 @@
android:id="@+id/udfps_touch_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <com.android.systemui.biometrics.UdfpsSurfaceView
+ android:id="@+id/hbm_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"/>
</com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay>
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index dc9c4f1..ff0031a 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -48,14 +48,14 @@
android:layout_height="@dimen/volume_row_slider_height">
<SeekBar
android:id="@+id/volume_row_slider"
- android:paddingLeft="0dp"
- android:paddingRight="0dp"
- android:paddingStart="0dp"
- android:paddingEnd="0dp"
+ android:paddingLeft="@dimen/rounded_slider_track_inset"
+ android:paddingRight="@dimen/rounded_slider_track_inset"
+ android:paddingStart="@dimen/rounded_slider_track_inset"
+ android:paddingEnd="@dimen/rounded_slider_track_inset"
android:layout_width="@dimen/volume_row_slider_height"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:thumb="@null"
+ android:thumb="@drawable/volume_row_seekbar_thumb"
android:splitTrack="false"
android:progressDrawable="@drawable/volume_row_seekbar"
android:background="@null"
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index c1eff5f..459f057 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -62,6 +62,11 @@
<!-- The color of the text in the Global Actions menu -->
<color name="global_actions_alert_text">@color/GM2_red_300</color>
+ <color name="global_actions_lite_background">@android:color/system_neutral1_800</color>
+ <color name="global_actions_lite_button_background">@android:color/system_accent1_100</color>
+ <color name="global_actions_lite_text">#ffffff</color>
+ <color name="global_actions_lite_icon">#000000</color>
+
<!-- Floating overlay actions -->
<color name="overlay_background_protection_start">#80000000</color> <!-- 50% black -->
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a375264..b3d51dd 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -38,9 +38,10 @@
<color name="global_actions_grid_background">#F1F3F4</color>
<!-- Colors for Power Menu Lite -->
- <color name="global_actions_lite_background">#191C18</color>
- <color name="global_actions_lite_button_background">#303030</color>
- <color name="global_actions_lite_text">#F0F0F0</color>
+ <color name="global_actions_lite_background">@android:color/system_neutral1_0</color>
+ <color name="global_actions_lite_button_background">@android:color/system_accent1_600</color>
+ <color name="global_actions_lite_text">#000000</color>
+ <color name="global_actions_lite_icon">#ffffff</color>
<color name="global_actions_lite_emergency_background">#F85D4D</color>
<color name="global_actions_lite_emergency_icon">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values/custom_config.xml b/packages/SystemUI/res/values/custom_config.xml
new file mode 100644
index 0000000..6f0bebf
--- /dev/null
+++ b/packages/SystemUI/res/values/custom_config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2009, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+
+ <!-- to hide statusbar and qs batteryy on unknown state
+ needed for battery less devices -->
+ <bool name="config_battery_hide_on_unknown">false</bool>
+
+ <!-- The default tiles to display in QuickSettings -->
+ <string name="quick_settings_tiles_extra" translatable="false">
+ aod,nfc,screenshot,caffeine,dataswitch
+ </string>
+
+ <!-- The CPU temperature sensor path, defaults to empty -->
+ <string name="config_cpuTempSensor" translatable="false"></string>
+ <!-- The battery temperature divider, if needed -->
+ <integer name="config_battTempDivider" translatable="false">10</integer>
+ <!-- The CPU temperature divider, if needed -->
+ <integer name="config_cpuTempDivider" translatable="false">1</integer>
+ <!-- The CPUs to display in CPUInfoService view -->
+ <string name="config_displayCpus" translatable="false"></string>
+
+ <!-- Navigation bar dpad -->
+ <string name="config_navBarLayoutHandleArrows" translatable="false">back[1.7WC];home_handle;ime_switcher[1.7WC]</string>
+
+ <!-- qs columns count settings -->
+ <bool name="qs_tile_vertical_layout">false</bool>
+
+ <!-- hack - we want a way to access the landscape default resource config -->
+ <!-- obviously whenever the default is changed or anyone wants
+ to use a different default in his device tree he must be aware of that -->
+ <integer name="quick_settings_num_columns_landscape">4</integer>
+
+ <!-- Color of the UDFPS pressed view -->
+ <color name="config_udfpsColor">#ffffffff</color>
+</resources>
diff --git a/packages/SystemUI/res/values/custom_dimens.xml b/packages/SystemUI/res/values/custom_dimens.xml
new file mode 100644
index 0000000..63ea702
--- /dev/null
+++ b/packages/SystemUI/res/values/custom_dimens.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2022, 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.
+*/
+-->
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <dimen name="cpu_info_text_height">12dp</dimen>
+
+ <!-- Navigation bar dpad -->
+ <dimen name="navigation_extra_key_width">36dp</dimen>
+
+ <dimen name="navigation_home_handle_small_width">40dp</dimen>
+ <!-- 2 * navigation_handle_radius + 2 * navigation_handle_bottom-->
+ <dimen name="navigation_home_handle_height">14dp</dimen>
+
+ <!-- Brightness and volume slider-->
+ <dimen name="rounded_slider_progress_width">8dp</dimen>
+ <dimen name="rounded_slider_progress_corner_radius">4dp</dimen>
+ <dimen name="rounded_slider_track_negative_inset">-22dp</dimen>
+ <dimen name="brightness_progress_padding">24dp</dimen>
+ <dimen name="volume_seekbar_progress_width">8dp</dimen>
+ <dimen name="volume_seekbar_progress_corner_radius">4dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values/custom_strings.xml b/packages/SystemUI/res/values/custom_strings.xml
new file mode 100644
index 0000000..1124ee3
--- /dev/null
+++ b/packages/SystemUI/res/values/custom_strings.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- alarm tile -->
+ <string name="alarm_title_dnd_indicator">(Off by DnD)</string>
+
+ <!-- AOD QS tile -->
+ <string name="quick_settings_aod_label">AOD</string>
+ <string name="quick_settings_aod_off_powersave_label">AOD off\nBattery saver</string>
+ <string name="aod_on">On</string>
+ <string name="aod_off">Off</string>
+
+ <!-- Caffeine QS tile -->
+ <string name="quick_settings_caffeine_label">Caffeine</string>
+ <string name="accessibility_quick_settings_caffeine_off">Caffeine off.</string>
+ <string name="accessibility_quick_settings_caffeine_on">Caffeine on.</string>
+
+ <!-- DataSwitch Tile -->
+ <string name="qs_data_switch_label">Switch data card</string>
+ <string name="qs_data_switch_changed_1">Using SIM 1 for Mobile data</string>
+ <string name="qs_data_switch_changed_2">Using SIM 2 for Mobile data</string>
+ <string name="qs_data_no_sim">No SIM</string>
+ <string name="qs_data_sim_1">SIM 1</string>
+ <string name="qs_data_sim_2">SIM 2</string>
+
+ <!-- Keyguard -->
+ <string name="keyguard_slice_dnd">Do Not Disturb</string>
+
+ <!-- Navigation bar dpad -->
+ <string name="accessibility_dpad_left">Cursor left</string>
+ <string name="accessibility_dpad_right">Cursor right</string>
+
+ <!-- Power menu reboot -->
+ <string name="global_action_reboot">Restart</string>
+ <string name="global_action_reboot_more">Restart\u2026</string>
+ <string name="global_action_reboot_sub">System</string>
+ <string name="global_action_reboot_recovery">Recovery</string>
+ <string name="global_action_reboot_bootloader">Bootloader</string>
+ <string name="global_action_reboot_fastboot">Fastboot</string>
+
+ <!-- Label for area where tiles can be added to the qs panel -->
+ <string name="drag_or_tap_to_add_tiles">Hold & drag or tap to add tiles</string>
+
+ <!-- Label for UI element which allows deleting the screenshot [CHAR LIMIT=30] -->
+ <string name="screenshot_delete_label">Delete</string>
+ <!-- Content description indicating that tapping the element will allow deleting the screenshot [CHAR LIMIT=NONE] -->
+ <string name="screenshot_delete_description">Delete screenshot</string>
+
+ <string name="screenshot_scroll_label_empty"></string>
+ <string name="screenshot_delete_label_empty"></string>
+ <string name="screenshot_edit_label_empty"></string>
+ <string name="screenshot_share_label_empty"></string>
+
+</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5894f29..6448ea8 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1073,8 +1073,8 @@
<dimen name="global_actions_power_dialog_item_bottom_margin">45dp</dimen>
<!-- Power Menu Lite -->
- <dimen name="global_actions_button_size">96dp</dimen>
- <dimen name="global_actions_button_padding">38dp</dimen>
+ <dimen name="global_actions_button_size">80dp</dimen>
+ <dimen name="global_actions_button_padding">24dp</dimen>
<dimen name="global_actions_corner_radius">28dp</dimen>
<dimen name="global_actions_lite_padding">24dp</dimen>
<dimen name="global_actions_info_margin">32dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 5af80cb..0c38057 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -41,6 +41,7 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.DisplaySpecific
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.Dependency
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags.REGION_SAMPLING
import com.android.systemui.keyguard.MigrateClocksToBlueprint
@@ -54,6 +55,7 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.core.Logger
import com.android.systemui.modes.shared.ModesUi
+import com.android.systemui.omni.OmniSettingsService
import com.android.systemui.plugins.clocks.AlarmData
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceController
@@ -72,6 +74,7 @@
import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.concurrency.DelayableExecutor
+import org.omnirom.omnilib.utils.OmniSettings
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.Executor
@@ -436,6 +439,13 @@
}
}
+ private val settingsListener = object : OmniSettingsService.OmniSettingsObserver {
+ override fun onIntSettingChanged(key: String, newValue: Int) {
+ clock?.events?.onColorPaletteChanged(resources)
+ updateColors()
+ }
+ }
+
private fun handleZenMode(zen: Int) {
val mode = ZenMode.fromInt(zen)
if (mode == null) {
@@ -495,6 +505,7 @@
}
smallTimeListener?.update(shouldTimeListenerRun)
largeTimeListener?.update(shouldTimeListenerRun)
+ Dependency.get(OmniSettingsService::class.java).addIntObserver(settingsListener, OmniSettings.OMNI_LOCKSCREEN_CLOCK_COLORED)
bgExecutor.execute {
// Query ZenMode data
@@ -521,6 +532,7 @@
largeRegionSampler?.stopRegionSampler()
smallTimeListener?.stop()
largeTimeListener?.stop()
+ Dependency.get(OmniSettingsService::class.java).removeObserver(settingsListener)
clock?.run {
smallClock.view.removeOnAttachStateChangeListener(smallClockOnAttachStateChangeListener)
largeClock.view.removeOnAttachStateChangeListener(largeClockOnAttachStateChangeListener)
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 40c1f0f9..b4d8a60 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -35,6 +35,7 @@
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBarController;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.VolumeDialogController;
@@ -52,6 +53,7 @@
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore;
import com.android.systemui.tuner.TunerService;
@@ -117,6 +119,7 @@
@Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher;
@Inject Lazy<BluetoothController> mBluetoothController;
+ @Inject Lazy<FlashlightController> mFlashlightController;
@Inject Lazy<KeyguardUpdateMonitor> mKeyguardUpdateMonitor;
@Inject Lazy<DeviceProvisionedController> mDeviceProvisionedController;
@Inject Lazy<PluginManager> mPluginManager;
@@ -132,6 +135,7 @@
@Inject Lazy<OverviewProxyService> mOverviewProxyService;
@Inject Lazy<NavigationModeController> mNavBarModeController;
@Inject Lazy<NavigationBarController> mNavigationBarController;
+ @Inject Lazy<OmniSettingsService> mOmniSettingsService;
@Inject Lazy<StatusBarStateController> mStatusBarStateController;
@Inject Lazy<NotificationMediaManager> mNotificationMediaManager;
@Inject @Background Lazy<Looper> mBgLooper;
@@ -164,6 +168,7 @@
mProviders.put(BG_LOOPER, mBgLooper::get);
mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get);
mProviders.put(BluetoothController.class, mBluetoothController::get);
+ mProviders.put(FlashlightController.class, mFlashlightController::get);
mProviders.put(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor::get);
mProviders.put(DeviceProvisionedController.class, mDeviceProvisionedController::get);
mProviders.put(PluginManager.class, mPluginManager::get);
@@ -178,6 +183,7 @@
mProviders.put(OverviewProxyService.class, mOverviewProxyService::get);
mProviders.put(NavigationModeController.class, mNavBarModeController::get);
mProviders.put(NavigationBarController.class, mNavigationBarController::get);
+ mProviders.put(OmniSettingsService.class, mOmniSettingsService::get);
mProviders.put(StatusBarStateController.class, mStatusBarStateController::get);
mProviders.put(NotificationMediaManager.class, mNotificationMediaManager::get);
mProviders.put(SysUiState.class, mSysUiStateFlagsContainer::get);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 1176cb0..28067f8 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -16,6 +16,7 @@
package com.android.systemui.battery;
import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+import static org.omnirom.omnilib.utils.OmniSettings.OMNI_SHOW_BATTERY_IMAGE;
import static com.android.settingslib.flags.Flags.newStatusBarIcons;
import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -43,6 +44,8 @@
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -92,6 +95,7 @@
private boolean mIsIncompatibleCharging;
// Error state where we know nothing about the current battery state
private boolean mBatteryStateUnknown;
+ private boolean mHideBatteryOnUnknown;
// Lazily-loaded since this is expected to be a rare-if-ever state
private Drawable mUnknownStateDrawable;
@@ -106,6 +110,8 @@
private BatteryDrawableState mUnifiedBatteryState =
BatteryDrawableState.Companion.getDefaultInitialState();
+ private boolean mHideImage;
+
public BatteryMeterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -127,6 +133,8 @@
mShowPercentAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_battery_percentage_setting_available);
+ mHideBatteryOnUnknown = context.getResources().getBoolean(
+ R.bool.config_battery_hide_on_unknown);
setupLayoutTransition();
@@ -153,6 +161,7 @@
}
updateShowPercent();
+
mDualToneHandler = new DualToneHandler(context);
// Init to not dark at all.
onDarkChanged(new ArrayList<Rect>(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
@@ -314,7 +323,7 @@
return;
}
mPowerSaveEnabled = isPowerSave;
- if (!newStatusBarIcons()) {
+ if (!newStatusBarIcons() || isImageHidden()) {
mDrawable.setPowerSaveEnabled(isPowerSave);
} else {
setBatteryDrawableState(
@@ -415,7 +424,7 @@
}
void updatePercentText() {
- if (!newStatusBarIcons()) {
+ if (!newStatusBarIcons() || mHideImage) {
updatePercentTextLegacy();
return;
}
@@ -527,7 +536,7 @@
}
void updateShowPercent() {
- if (!newStatusBarIcons()) {
+ if (!newStatusBarIcons() || mHideImage) {
updateShowPercentLegacy();
return;
}
@@ -556,10 +565,11 @@
// The legacy impl used the percent view for the estimate and the percent text. The modern
// version only uses it for estimate. It can be safely removed here
- if (mShowPercentMode != MODE_ESTIMATE) {
+ // Omni: Don't remove mBatteryPercentView for percent on lockscreen with hideImage
+ /*if (mShowPercentMode != MODE_ESTIMATE) {
removeView(mBatteryPercentView);
mBatteryPercentView = null;
- }
+ }*/
}
private void updateShowPercentLegacy() {
@@ -589,6 +599,23 @@
}
}
+ void updateShowImage() {
+ mHideImage = Settings.System.getIntForUser(getContext().getContentResolver(),
+ OMNI_SHOW_BATTERY_IMAGE, 1, UserHandle.USER_CURRENT) == 0;
+ mBatteryIconView.setVisibility(mHideImage ? View.GONE : View.VISIBLE);
+ if (mHideImage) {
+ updateShowPercentLegacy();
+ updatePercentTextLegacy();
+ } else {
+ removeView(mBatteryPercentView);
+ mBatteryPercentView = null;
+ }
+ }
+
+ boolean isImageHidden() {
+ return mHideImage && mBatteryPercentView != null;
+ }
+
private Drawable getUnknownStateDrawable() {
if (mUnknownStateDrawable == null) {
mUnknownStateDrawable = mContext.getDrawable(R.drawable.ic_battery_unknown);
@@ -608,13 +635,29 @@
if (mBatteryStateUnknown) {
mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
+ if (mHideBatteryOnUnknown) {
+ setVisibility(View.GONE);
+ }
} else {
mBatteryIconView.setImageDrawable(mDrawable);
+ setVisibility(View.VISIBLE);
}
updateShowPercent();
}
+ @Override
+ public void setVisibility(@Visibility int visibility) {
+ if (visibility == View.VISIBLE && isBatteryHidden()) {
+ return;
+ }
+ super.setVisibility(visibility);
+ }
+
+ boolean isBatteryHidden() {
+ return mBatteryStateUnknown && mHideBatteryOnUnknown;
+ }
+
void scaleBatteryMeterViews() {
if (!newStatusBarIcons()) {
scaleBatteryMeterViewsLegacy();
@@ -695,7 +738,7 @@
public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
if (mIsStaticColor) return;
- if (!newStatusBarIcons()) {
+ if (!newStatusBarIcons() || isImageHidden()) {
onDarkChangedLegacy(areas, darkIntensity, tint);
return;
}
@@ -755,7 +798,7 @@
/** For newStatusBarIcons(), we use a BatteryColors object to declare the theme */
public void setUnifiedBatteryColors(BatteryColors colors) {
- if (!newStatusBarIcons()) return;
+ if (!newStatusBarIcons() || isImageHidden()) return;
mUnifiedBatteryColors = colors;
mUnifiedBattery.setColors(mUnifiedBatteryColors);
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index 9a30c21..fc49a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -16,6 +16,7 @@
package com.android.systemui.battery;
import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+import static org.omnirom.omnilib.utils.OmniSettings.OMNI_SHOW_BATTERY_IMAGE;
import android.content.ContentResolver;
import android.content.Context;
@@ -74,7 +75,7 @@
if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
ArraySet<String> icons = StatusBarIconController.getIconHideList(
getContext(), newValue);
- mView.setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
+ mView.setVisibility((icons.contains(mSlotBattery) || mView.isBatteryHidden()) ? View.GONE : View.VISIBLE);
}
}
};
@@ -168,6 +169,8 @@
mUserTracker.addCallback(mUserChangedCallback, new HandlerExecutor(mMainHandler));
mView.updateShowPercent();
+ mView.updateShowImage();
+ mView.isImageHidden();
}
@Override
@@ -213,6 +216,11 @@
false,
mSettingObserver,
user);
+ mContentResolver.registerContentObserver(
+ Settings.System.getUriFor(OMNI_SHOW_BATTERY_IMAGE),
+ false,
+ mSettingObserver,
+ user);
}
private void registerGlobalBatteryUpdateObserver() {
@@ -231,6 +239,8 @@
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
mView.updateShowPercent();
+ mView.updateShowImage();
+ mView.isImageHidden();
if (TextUtils.equals(uri.getLastPathSegment(),
Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME)) {
// update the text for sure if the estimate in the cache was updated
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 4c2dc41..e2be047 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -29,6 +29,7 @@
import android.view.animation.PathInterpolator
import com.android.internal.graphics.ColorUtils
import com.android.app.animation.Interpolators
+import com.android.settingslib.Utils
import com.android.systemui.surfaceeffects.ripple.RippleShader
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
@@ -89,7 +90,8 @@
rippleShader.sparkleStrength = RIPPLE_SPARKLE_STRENGTH
updateRippleFadeParams()
ripplePaint.shader = rippleShader
- setLockScreenColor(0xffffffff.toInt()) // default color
+ setLockScreenColor(Utils.getColorAttr(context,
+ android.R.attr.colorAccent).defaultColor) // default color
dwellShader.color = 0xffffffff.toInt() // default color
dwellShader.progress = 0f
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index a9133e4..2b2d85d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -79,6 +79,7 @@
import com.android.systemui.biometrics.udfps.SinglePointerTouchProcessor;
import com.android.systemui.biometrics.udfps.TouchProcessor;
import com.android.systemui.biometrics.udfps.TouchProcessorResult;
+import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay;
import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayViewModel;
import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel;
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
@@ -865,8 +866,9 @@
if (!isOptical()) {
return;
}
- if (mUdfpsDisplayMode != null) {
- mUdfpsDisplayMode.disable(null);
+ UdfpsTouchOverlay udfpsView = (UdfpsTouchOverlay) view;
+ if (udfpsView.isDisplayConfigured()) {
+ udfpsView.unconfigureDisplay();
}
}
@@ -1059,7 +1061,7 @@
if (mIgnoreRefreshRate) {
dispatchOnUiReady(requestId);
} else {
- mUdfpsDisplayMode.enable(() -> dispatchOnUiReady(requestId));
+ ((UdfpsTouchOverlay) view).configureDisplay(() -> dispatchOnUiReady(requestId));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index 51eb139..6da2743 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -198,6 +198,7 @@
(inflater.inflate(R.layout.udfps_touch_overlay, null, false)
as UdfpsTouchOverlay)
.apply {
+ setUdfpsDisplayModeProvider(udfpsDisplayModeProvider)
// This view overlaps the sensor area
// prevent it from being selectable during a11y
if (requestReason.isImportantForAccessibility()) {
@@ -219,6 +220,7 @@
udfpsOverlayInteractor = udfpsOverlayInteractor,
)
}
+ sensorRect = sensorBounds
}
getTouchOverlay()?.apply {
@@ -291,6 +293,11 @@
fun hide(): Boolean {
val wasShowing = isShowing
+ overlayTouchView?.apply {
+ if (isDisplayConfigured) {
+ unconfigureDisplay()
+ }
+ }
udfpsDisplayModeProvider.disable(null)
getTouchOverlay()?.apply {
if (this.parent != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java
new file mode 100644
index 0000000..3bfddde
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2021 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.biometrics;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import com.android.systemui.res.R;
+
+/**
+ * Surface View for providing the Global High-Brightness Mode (GHBM) illumination for UDFPS.
+ */
+public class UdfpsSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+ private static final String TAG = "UdfpsSurfaceView";
+
+ /**
+ * Notifies {@link UdfpsView} when to enable GHBM illumination.
+ */
+ interface GhbmIlluminationListener {
+ /**
+ * @param surface the surface for which GHBM should be enabled.
+ * @param onDisplayConfigured a runnable that should be run after GHBM is enabled.
+ */
+ void enableGhbm(@NonNull Surface surface, @Nullable Runnable onDisplayConfigured);
+ }
+
+ @NonNull private final SurfaceHolder mHolder;
+ @NonNull private final Paint mSensorPaint;
+
+ @Nullable private GhbmIlluminationListener mGhbmIlluminationListener;
+ @Nullable private Runnable mOnDisplayConfigured;
+ boolean mAwaitingSurfaceToStartIllumination;
+ boolean mHasValidSurface;
+
+ private Drawable mUdfpsIconPressed;
+
+ public UdfpsSurfaceView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ // Make this SurfaceView draw on top of everything else in this window. This allows us to
+ // 1) Always show the HBM circle on top of everything else, and
+ // 2) Properly composite this view with any other animations in the same window no matter
+ // what contents are added in which order to this view hierarchy.
+ setZOrderOnTop(true);
+
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ mHolder.setFormat(PixelFormat.RGBA_8888);
+
+ mSensorPaint = new Paint(0 /* flags */);
+ mSensorPaint.setAntiAlias(true);
+ mSensorPaint.setColor(context.getColor(R.color.config_udfpsColor));
+ mSensorPaint.setStyle(Paint.Style.FILL);
+
+ mUdfpsIconPressed = context.getDrawable(R.drawable.udfps_icon_pressed);
+ }
+
+ @Override public void surfaceCreated(SurfaceHolder holder) {
+ mHasValidSurface = true;
+ if (mAwaitingSurfaceToStartIllumination) {
+ doIlluminate(mOnDisplayConfigured);
+ mOnDisplayConfigured = null;
+ mAwaitingSurfaceToStartIllumination = false;
+ }
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ // Unused.
+ }
+
+ @Override public void surfaceDestroyed(SurfaceHolder holder) {
+ mHasValidSurface = false;
+ }
+
+ public void setGhbmIlluminationListener(@Nullable GhbmIlluminationListener listener) {
+ mGhbmIlluminationListener = listener;
+ }
+
+ /**
+ * Note: there is no corresponding method to stop GHBM illumination. It is expected that
+ * {@link UdfpsView} will hide this view, which would destroy the surface and remove the
+ * illumination dot.
+ */
+ public void startGhbmIllumination(@Nullable Runnable onDisplayConfigured) {
+ if (mGhbmIlluminationListener == null) {
+ Log.e(TAG, "startIllumination | mGhbmIlluminationListener is null");
+ return;
+ }
+
+ if (mHasValidSurface) {
+ doIlluminate(onDisplayConfigured);
+ } else {
+ mAwaitingSurfaceToStartIllumination = true;
+ mOnDisplayConfigured = onDisplayConfigured;
+ }
+ }
+
+ private void doIlluminate(@Nullable Runnable onDisplayConfigured) {
+ if (mGhbmIlluminationListener == null) {
+ Log.e(TAG, "doIlluminate | mGhbmIlluminationListener is null");
+ return;
+ }
+
+ mGhbmIlluminationListener.enableGhbm(mHolder.getSurface(), onDisplayConfigured);
+ }
+
+ /**
+ * Immediately draws the illumination dot on this SurfaceView's surface.
+ */
+ public void drawIlluminationDot(@NonNull RectF sensorRect) {
+ if (!mHasValidSurface) {
+ Log.e(TAG, "drawIlluminationDot | the surface is destroyed or was never created.");
+ return;
+ }
+ Canvas canvas = null;
+ try {
+ canvas = mHolder.lockCanvas();
+ mUdfpsIconPressed.setBounds(
+ Math.round(sensorRect.left),
+ Math.round(sensorRect.top),
+ Math.round(sensorRect.right),
+ Math.round(sensorRect.bottom)
+ );
+ mUdfpsIconPressed.draw(canvas);
+ canvas.drawOval(sensorRect, mSensorPaint);
+ } finally {
+ // Make sure the surface is never left in a bad state.
+ if (canvas != null) {
+ mHolder.unlockCanvasAndPost(canvas);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt
index 2484c33..484f2bb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt
@@ -16,11 +16,65 @@
package com.android.systemui.biometrics.ui.view
import android.content.Context
+import android.graphics.Rect
+import android.graphics.RectF
import android.util.AttributeSet
+import android.view.Surface
import android.widget.FrameLayout
+import com.android.systemui.biometrics.UdfpsDisplayModeProvider
+import com.android.systemui.biometrics.UdfpsSurfaceView
+import com.android.systemui.res.R
+
/**
* A translucent (not visible to the user) view that receives touches to send to FingerprintManager
* for fingerprint authentication.
*/
-class UdfpsTouchOverlay(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs)
+class UdfpsTouchOverlay(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
+ private var ghbmView: UdfpsSurfaceView? = null
+ private var udfpsDisplayMode: UdfpsDisplayModeProvider? = null
+
+ // sensorRect may be bigger than the sensor. True sensor dimensions are defined in
+ // overlayParams.sensorBounds
+ var sensorRect = Rect()
+
+ /** True after the call to [configureDisplay] and before the call to [unconfigureDisplay]. */
+ var isDisplayConfigured: Boolean = false
+ private set
+
+ override fun onFinishInflate() {
+ ghbmView = findViewById(R.id.hbm_view)
+ }
+
+ fun setUdfpsDisplayModeProvider(udfpsDisplayModeProvider: UdfpsDisplayModeProvider?) {
+ udfpsDisplayMode = udfpsDisplayModeProvider
+ }
+
+ fun configureDisplay(onDisplayConfigured: Runnable) {
+ isDisplayConfigured = true
+ val gView = ghbmView
+ if (gView != null) {
+ gView.setGhbmIlluminationListener(this::doIlluminate)
+ gView.visibility = VISIBLE
+ gView.startGhbmIllumination(onDisplayConfigured)
+ } else {
+ doIlluminate(null /* surface */, onDisplayConfigured)
+ }
+ }
+
+ private fun doIlluminate(surface: Surface?, onDisplayConfigured: Runnable?) {
+ udfpsDisplayMode?.enable {
+ onDisplayConfigured?.run()
+ ghbmView?.drawIlluminationDot(RectF(sensorRect))
+ }
+ }
+
+ fun unconfigureDisplay() {
+ isDisplayConfigured = false
+ ghbmView?.let { view ->
+ view.setGhbmIlluminationListener(null)
+ view.visibility = INVISIBLE
+ }
+ udfpsDisplayMode?.disable(null /* onDisabled */)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 5a0eb72..93f6a1b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -24,6 +24,7 @@
import com.android.systemui.media.dialog.MediaOutputDialogReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetPinnedReceiver;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
+import com.android.systemui.screenshot.DeleteScreenshotReceiver;
import com.android.systemui.screenshot.SmartActionsReceiver;
import dagger.Binds;
@@ -41,6 +42,15 @@
*/
@Binds
@IntoMap
+ @ClassKey(DeleteScreenshotReceiver.class)
+ public abstract BroadcastReceiver bindDeleteScreenshotReceiver(
+ DeleteScreenshotReceiver broadcastReceiver);
+
+ /**
+ *
+ */
+ @Binds
+ @IntoMap
@ClassKey(SmartActionsReceiver.class)
public abstract BroadcastReceiver bindSmartActionsReceiver(
SmartActionsReceiver broadcastReceiver);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index fcc3ea9..4e437f7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -49,6 +49,7 @@
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderCoordinator
import com.android.systemui.mediaprojection.taskswitcher.MediaProjectionTaskSwitcherCoreStartable
+import com.android.systemui.omni.CPUInfoManager
import com.android.systemui.settings.MultiUserUtilsModule
import com.android.systemui.shortcut.ShortcutKeyDispatcher
import com.android.systemui.statusbar.ImmersiveModeConfirmation
@@ -353,4 +354,10 @@
@IntoMap
@ClassKey(ComplicationTypesUpdater::class)
abstract fun bindComplicationTypesUpdater(updater: ComplicationTypesUpdater): CoreStartable
+
+ /** Inject into Omni CPUInfoManager. */
+ @Binds
+ @IntoMap
+ @ClassKey(CPUInfoManager::class)
+ abstract fun bindCPUInfoManager(sysui: CPUInfoManager): CoreStartable
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index d6f8957..67fbfdc 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -89,6 +89,7 @@
import com.android.systemui.navigationbar.NavigationBarComponent;
import com.android.systemui.navigationbar.gestural.dagger.GestureModule;
import com.android.systemui.notetask.NoteTaskModule;
+import com.android.systemui.omni.dagger.OmniModule;
import com.android.systemui.people.PeopleModule;
import com.android.systemui.plugins.BcSmartspaceConfigPlugin;
import com.android.systemui.plugins.BcSmartspaceDataPlugin;
@@ -281,6 +282,7 @@
UserModule.class,
UtilModule.class,
NoteTaskModule.class,
+ OmniModule.class,
WalletModule.class
},
subcomponents = {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index 9f321d8..ed6ab98 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -78,8 +78,8 @@
}
@Override
- public void handleShowShutdownUi(boolean isReboot, String reason) {
- mExtension.get().showShutdownUi(isReboot, reason);
+ public void handleShowShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
+ mExtension.get().showShutdownUi(isReboot, reason, rebootCustom);
}
@Override
@@ -114,9 +114,9 @@
}
@Override
- public void reboot(boolean safeMode) {
+ public void reboot(boolean safeMode, String reason) {
try {
- mBarService.reboot(safeMode);
+ mBarService.reboot(safeMode, reason);
} catch (RemoteException e) {
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 91b44e7..5d5ca2a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -57,6 +57,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.Trace;
@@ -143,6 +144,8 @@
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@@ -188,6 +191,9 @@
static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
static final String GLOBAL_ACTION_KEY_SYSTEM_UPDATE = "system_update";
+ private static final String GLOBAL_ACTION_KEY_REBOOT_RECOVERY = "reboot_recovery";
+ private static final String GLOBAL_ACTION_KEY_REBOOT_BOOTLOADER = "reboot_bootloader";
+ private static final String GLOBAL_ACTION_KEY_REBOOT_FASTBOOT = "reboot_fastboot";
// See NotificationManagerService#scheduleDurationReachedLocked
private static final long TOAST_FADE_TIME = 333;
@@ -262,6 +268,12 @@
private final UserLogoutInteractor mLogoutInteractor;
private final GlobalActionsInteractor mInteractor;
+ // omni additions start
+ private String[] mRootMenuActions;
+ private String[] mRebootMenuActions;
+ private String[] mCurrentMenuActions;
+ private boolean mRebootMenu;
+
@VisibleForTesting
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "The global actions / power menu surface became visible on the screen.")
@@ -442,6 +454,11 @@
mScreenshotHelper = new ScreenshotHelper(context);
mConfigurationController.addCallback(this);
+
+ mRootMenuActions = mContext.getResources().getStringArray(
+ R.array.config_globalActionsList);
+ mRebootMenuActions = mContext.getResources().getStringArray(
+ org.omnirom.omnilib.R.array.config_rebootActionsList);
}
/**
@@ -478,6 +495,8 @@
@Nullable Expandable expandable) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
+ mRebootMenu = false;
+ mCurrentMenuActions = mRootMenuActions;
if (mDialog != null && mDialog.isShowing()) {
// In order to force global actions to hide on the same affordance press, we must
// register a call to onGlobalActionsShown() first to prevent the default actions
@@ -588,22 +607,25 @@
mItems.clear();
mOverflowItems.clear();
mPowerItems.clear();
- String[] defaultActions = getDefaultActions();
ShutDownAction shutdownAction = new ShutDownAction();
RestartAction restartAction = new RestartAction();
+ RebootRecoveryAction rebootRecoveryAction = new RebootRecoveryAction();
+ RebootBootloaderAction rebootBootloaderAction = new RebootBootloaderAction();
+ RebootFastbootAction rebootFastbootAction = new RebootFastbootAction();
+
ArraySet<String> addedKeys = new ArraySet<>();
List<Action> tempActions = new ArrayList<>();
CurrentUserProvider currentUser = new CurrentUserProvider();
// make sure emergency affordance action is first, if needed
- if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
+ if (mEmergencyAffordanceManager.needsEmergencyAffordance() && !mRebootMenu) {
addIfShouldShowAction(tempActions, new EmergencyAffordanceAction());
addedKeys.add(GLOBAL_ACTION_KEY_EMERGENCY);
}
- for (int i = 0; i < defaultActions.length; i++) {
- String actionKey = defaultActions[i];
+ for (int i = 0; i < mCurrentMenuActions.length; i++) {
+ String actionKey = mCurrentMenuActions[i];
if (addedKeys.contains(actionKey)) {
// If we already have added this, don't add it again.
continue;
@@ -648,6 +670,12 @@
}
} else if (GLOBAL_ACTION_KEY_SYSTEM_UPDATE.equals(actionKey)) {
addIfShouldShowAction(tempActions, new SystemUpdateAction());
+ } else if (GLOBAL_ACTION_KEY_REBOOT_RECOVERY.equals(actionKey)) {
+ addIfShouldShowAction(tempActions, rebootRecoveryAction);
+ } else if (GLOBAL_ACTION_KEY_REBOOT_BOOTLOADER.equals(actionKey)) {
+ addIfShouldShowAction(tempActions, rebootBootloaderAction);
+ } else if (GLOBAL_ACTION_KEY_REBOOT_FASTBOOT.equals(actionKey)) {
+ addIfShouldShowAction(tempActions, rebootFastbootAction);
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -666,6 +694,15 @@
mPowerItems.add(shutdownAction);
mPowerItems.add(restartAction);
+ if (advancedRebootEnabled(mContext)) {
+ tempActions.remove(rebootRecoveryAction);
+ tempActions.remove(rebootBootloaderAction);
+ tempActions.remove(rebootFastbootAction);
+ mPowerItems.add(rebootRecoveryAction);
+ mPowerItems.add(rebootBootloaderAction);
+ mPowerItems.add(rebootFastbootAction);
+ }
+
// add the PowerOptionsAction after Emergency, if present
tempActions.add(powerOptionsIndex, new PowerOptionsAction());
}
@@ -720,6 +757,19 @@
return dialog;
}
+ private boolean advancedRebootEnabled(Context context) {
+ boolean advancedRebootEnabled = Settings.System.getIntForUser(context.getContentResolver(),
+ OmniSettings.OMNI_ADVANCED_REBOOT, 0, UserHandle.USER_CURRENT) == 1;
+ return advancedRebootEnabled;
+ }
+
+ private boolean isSecureLocked() {
+ if (mKeyguardShowing) {
+ return mKeyguardStateController.isUnlocked();
+ }
+ return false;
+ }
+
@VisibleForTesting
boolean shouldDisplayLockdown(UserInfo user) {
if (user == null) {
@@ -813,7 +863,7 @@
}
mUiEventLogger.log(GlobalActionsEvent.GA_SHUTDOWN_LONG_PRESS);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
- mWindowManagerFuncs.reboot(true);
+ mWindowManagerFuncs.reboot(true, null);
return true;
}
return false;
@@ -942,7 +992,12 @@
@VisibleForTesting
final class RestartAction extends SinglePressAction implements LongPressAction {
RestartAction() {
- super(R.drawable.ic_restart, R.string.global_action_restart);
+ super(R.drawable.ic_restart, com.android.systemui.R.string.global_action_reboot);
+ if (mRebootMenu) {
+ mMessageResId = com.android.systemui.R.string.global_action_reboot_sub;
+ } else if (advancedRebootEnabled(mContext)) {
+ mMessageResId = com.android.systemui.R.string.global_action_reboot_more;
+ }
}
@Override
@@ -954,7 +1009,7 @@
}
mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_LONG_PRESS);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {
- mWindowManagerFuncs.reboot(true);
+ mWindowManagerFuncs.reboot(true, null);
return true;
}
return false;
@@ -978,7 +1033,82 @@
return;
}
mUiEventLogger.log(GlobalActionsEvent.GA_REBOOT_PRESS);
- mWindowManagerFuncs.reboot(false);
+ if (!mRebootMenu && advancedRebootEnabled(mContext) && !isSecureLocked()) {
+ mRebootMenu = true;
+ mCurrentMenuActions = mRebootMenuActions;
+ createActionItems();
+ mDialog.updateList();
+ } else {
+ doReboot();
+ }
+ }
+
+ private void doReboot() {
+ mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);
+ mWindowManagerFuncs.reboot(false, null);
+ }
+ }
+
+ private final class RebootRecoveryAction extends SinglePressAction {
+ private RebootRecoveryAction() {
+ super(com.android.systemui.R.drawable.ic_restart_recovery, com.android.systemui.R.string.global_action_reboot_recovery);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_RECOVERY);
+ }
+ }
+
+ private final class RebootBootloaderAction extends SinglePressAction {
+ private RebootBootloaderAction() {
+ super(com.android.systemui.R.drawable.ic_restart_bootloader, com.android.systemui.R.string.global_action_reboot_bootloader);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_BOOTLOADER);
+ }
+ }
+
+ private final class RebootFastbootAction extends SinglePressAction {
+ private RebootFastbootAction() {
+ super(com.android.systemui.R.drawable.ic_restart_fastboot, com.android.systemui.R.string.global_action_reboot_fastboot);
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void onPress() {
+ mWindowManagerFuncs.reboot(false, PowerManager.REBOOT_FASTBOOT);
}
}
@@ -1373,6 +1503,14 @@
mInteractor.onShown();
}
+ public void onClick(DialogInterface dialog, int which) {
+ Action item = mAdapter.getItem(which);
+ if (!(item instanceof SilentModeTriStateAction) && !(item instanceof RestartAction)) {
+ dialog.dismiss();
+ }
+ item.onPress();
+ }
+
/**
* The adapter used for power menu items shown in the global actions dialog.
*/
@@ -1479,7 +1617,7 @@
if (!(item instanceof SilentModeTriStateAction)) {
if (mDialog != null) {
// don't dismiss the dialog if we're opening the power options menu
- if (!(item instanceof PowerOptionsAction)) {
+ if (!(item instanceof PowerOptionsAction) && !(item instanceof RestartAction)) {
// Usually clicking an item shuts down the phone, locks, or starts an
// activity. We don't want to animate back into the power button when that
// happens, so we disable the dialog animation before dismissing.
@@ -1745,7 +1883,7 @@
private abstract class SinglePressAction implements Action {
private final int mIconResId;
private final Drawable mIcon;
- private final int mMessageResId;
+ protected int mMessageResId;
private final CharSequence mMessage;
protected SinglePressAction(int iconResId, int messageResId) {
@@ -2764,5 +2902,9 @@
public void onRotate(int from, int to) {
refreshDialog();
}
+
+ public void updateList() {
+ mGlobalActionsLayout.updateList();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index c5027cc..e565ee1 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -67,9 +67,10 @@
}
@Override
- public void showShutdownUi(boolean isReboot, String reason) {
- mShutdownUi.showShutdownUi(isReboot, reason);
+ public void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
+ mShutdownUi.showShutdownUi(isReboot, reason, rebootCustom);
}
+
@Override
public void disable(int displayId, int state1, int state2, boolean animate) {
final boolean disabled = (state2 & DISABLE2_GLOBAL_ACTIONS) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
index 4599afa..db87923 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ShutdownUi.java
@@ -60,7 +60,7 @@
* @param reason Cause for the shutdown.
* @return Shutdown dialog.
*/
- public Dialog showShutdownUi(boolean isReboot, String reason) {
+ public Dialog showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
ScrimDrawable background = new ScrimDrawable();
final Dialog d = new Dialog(mContext,
@@ -110,8 +110,8 @@
reasonView.setTextColor(color);
messageView.setTextColor(color);
- messageView.setText(getRebootMessage(isReboot, reason));
- String rebootReasonMessage = getReasonMessage(reason);
+ messageView.setText(getRebootMessage(isReboot, reason, rebootCustom));
+ String rebootReasonMessage = getReasonMessage(reason, rebootCustom);
if (rebootReasonMessage != null) {
reasonView.setVisibility(View.VISIBLE);
reasonView.setText(rebootReasonMessage);
@@ -147,11 +147,17 @@
}
@StringRes
- @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason) {
+ @VisibleForTesting int getRebootMessage(boolean isReboot, @Nullable String reason, boolean custom) {
if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
return R.string.reboot_to_update_reboot;
- } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
+ } else if (reason != null && !custom && reason.equals(PowerManager.REBOOT_RECOVERY)) {
return R.string.reboot_to_reset_message;
+ } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
+ return org.omnirom.omnilib.R.string.reboot_to_recovery_message;
+ } else if (reason != null && reason.equals(PowerManager.REBOOT_BOOTLOADER)) {
+ return org.omnirom.omnilib.R.string.reboot_to_bootloader_message;
+ } else if (reason != null && reason.equals(PowerManager.REBOOT_FASTBOOT)) {
+ return org.omnirom.omnilib.R.string.reboot_to_fastboot_message;
} else if (isReboot) {
return R.string.reboot_to_reset_message;
} else {
@@ -160,10 +166,10 @@
}
@Nullable
- @VisibleForTesting String getReasonMessage(@Nullable String reason) {
+ @VisibleForTesting String getReasonMessage(@Nullable String reason, boolean custom) {
if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
return mContext.getString(R.string.reboot_to_update_title);
- } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY)) {
+ } else if (reason != null && reason.equals(PowerManager.REBOOT_RECOVERY) && !custom) {
return mContext.getString(R.string.reboot_to_reset_title);
} else {
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 3b85b57..eccdba9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -18,12 +18,14 @@
import android.annotation.AnyThread;
import android.app.AlarmManager;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.ContentObserver;
import android.graphics.Typeface;
import android.graphics.drawable.Icon;
import android.icu.text.DateFormat;
@@ -33,6 +35,7 @@
import android.net.Uri;
import android.os.Handler;
import android.os.Trace;
+import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
@@ -45,12 +48,15 @@
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
+import androidx.slice.widget.SliceViewUtil;
import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Dependency;
import com.android.systemui.SystemUIAppComponentFactoryBase;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
@@ -64,6 +70,9 @@
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.util.wakelock.WakeLockLogger;
+import org.omnirom.omnilib.utils.OmniSettings;
+import org.omnirom.omnilib.weather.OmniJawsClient;
+
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -80,7 +89,8 @@
public class KeyguardSliceProvider extends SliceProvider implements
NextAlarmController.NextAlarmChangeCallback, ZenModeController.Callback,
NotificationMediaManager.MediaListener, StatusBarStateController.StateListener,
- SystemUIAppComponentFactoryBase.ContextInitializer {
+ SystemUIAppComponentFactoryBase.ContextInitializer, OmniJawsClient.OmniJawsObserver,
+ OmniSettingsService.OmniSettingsObserver {
private static final String TAG = "KgdSliceProvider";
@@ -96,6 +106,7 @@
"content://com.android.systemui.keyguard/media";
public static final String KEYGUARD_ACTION_URI =
"content://com.android.systemui.keyguard/action";
+ public static final String KEYGUARD_WEATHER_URI = "content://com.android.systemui.keyguard/weather";
/**
* Only show alarms that will ring within N hours.
@@ -157,6 +168,14 @@
@Background
Handler mBgHandler;
+ protected final Uri mWeatherUri;
+ private OmniJawsClient mWeatherClient;
+ private OmniJawsClient.WeatherInfo mWeatherData;
+ private boolean mShowWeatherSlice;
+ private boolean mShowAlarmSlice = true;
+ private boolean mShowDndSlice;
+ private boolean mAlarmSliceTimed;
+
/**
* Receiver responsible for time ticking and updating the date format.
*/
@@ -208,6 +227,7 @@
mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
mDndUri = Uri.parse(KEYGUARD_DND_URI);
mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
+ mWeatherUri = Uri.parse(KEYGUARD_WEATHER_URI);
}
@AnyThread
@@ -227,6 +247,7 @@
addNextAlarmLocked(builder);
addZenModeLocked(builder);
addPrimaryActionLocked(builder);
+ addWeatherLocked(builder);
slice = builder.build();
}
} catch (IllegalStateException e) {
@@ -281,28 +302,42 @@
}
protected void addNextAlarmLocked(ListBuilder builder) {
- if (TextUtils.isEmpty(mNextAlarm)) {
+ if (TextUtils.isEmpty(mNextAlarm) || !mShowAlarmSlice) {
return;
}
+ final boolean zenNone = !zenAllowsAlarm();
IconCompat alarmIcon = IconCompat.createWithResource(getContext(),
- R.drawable.ic_access_alarms_big);
+ zenNone ? R.drawable.ic_access_alarms_big_dim : R.drawable.ic_access_alarms_big);
RowBuilder alarmRowBuilder = new RowBuilder(mAlarmUri)
.setTitle(mNextAlarm)
.addEndItem(alarmIcon, ListBuilder.ICON_IMAGE);
builder.addRow(alarmRowBuilder);
}
+ protected void addWeatherLocked(ListBuilder builder) {
+ if (!mShowWeatherSlice || !mWeatherClient.isOmniJawsEnabled() || mWeatherData == null) {
+ return;
+ }
+ IconCompat weatherIcon = SliceViewUtil.createIconFromDrawable(mWeatherClient.getWeatherConditionImage(mWeatherData.conditionCode));
+ RowBuilder weatherRowBuilder = new RowBuilder(mWeatherUri)
+ .setTitle(mWeatherData.temp + " " + mWeatherData.tempUnits + " " + mWeatherData.city)
+ .addEndItem(weatherIcon, ListBuilder.ICON_IMAGE);
+ builder.addRow(weatherRowBuilder);
+ }
+
/**
* Add zen mode (DND) icon to slice if it's enabled.
* @param builder The slice builder.
*/
protected void addZenModeLocked(ListBuilder builder) {
- if (!isDndOn()) {
+ if (!isDndOn() || !mShowDndSlice) {
return;
}
RowBuilder dndBuilder = new RowBuilder(mDndUri)
.setContentDescription(getContext().getResources()
.getString(R.string.accessibility_quick_settings_dnd))
+ .setTitle(getContext().getResources()
+ .getString(R.string.keyguard_slice_dnd))
.addEndItem(
IconCompat.createWithResource(getContext(), R.drawable.stat_sys_dnd),
ListBuilder.ICON_IMAGE);
@@ -342,6 +377,9 @@
KeyguardSliceProvider.sInstance = this;
registerClockUpdate();
updateClockLocked();
+ Dependency.get(OmniSettingsService.class).addIntObserver(this, OmniSettings.OMNI_LOCKSCREEN_WEATHER_ENABLED,
+ OmniSettings.OMNI_LOCKSCREEN_ALARM_ENABLED, OmniSettings.OMNI_LOCKSCREEN_DND_ENABLED);
+ enableWeatherUpdates();
}
return true;
}
@@ -358,6 +396,8 @@
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
getContext().unregisterReceiver(mIntentReceiver);
}
+ disableWeatherUpdates();
+ Dependency.get(OmniSettingsService.class).removeObserver(this);
KeyguardSliceProvider.sInstance = null;
}
}
@@ -375,8 +415,9 @@
private void updateNextAlarm() {
synchronized (this) {
if (withinNHoursLocked(mNextAlarmInfo, ALARM_VISIBILITY_HOURS)) {
- String pattern = android.text.format.DateFormat.is24HourFormat(getContext(),
- mUserTracker.getUserId()) ? "HH:mm" : "h:mm";
+ String skeleton = android.text.format.DateFormat.is24HourFormat(getContext(),
+ mUserTracker.getUserId()) ? "EHm" : "Ehma";
+ String pattern = android.text.format.DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
mNextAlarm = android.text.format.DateFormat.format(pattern,
mNextAlarmInfo.getTriggerTime()).toString();
} else {
@@ -391,6 +432,9 @@
return false;
}
+ if (!mAlarmSliceTimed) {
+ return true;
+ }
long limit = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(hours);
return mNextAlarmInfo.getTriggerTime() <= limit;
}
@@ -457,13 +501,15 @@
public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
synchronized (this) {
mNextAlarmInfo = nextAlarm;
- mAlarmManager.cancel(mUpdateNextAlarm);
+ if (mAlarmSliceTimed) {
+ mAlarmManager.cancel(mUpdateNextAlarm);
- long triggerAt = mNextAlarmInfo == null ? -1 : mNextAlarmInfo.getTriggerTime()
- - TimeUnit.HOURS.toMillis(ALARM_VISIBILITY_HOURS);
- if (triggerAt > 0) {
- mAlarmManager.setExact(AlarmManager.RTC, triggerAt, "lock_screen_next_alarm",
- mUpdateNextAlarm, mHandler);
+ long triggerAt = mNextAlarmInfo == null ? -1 : mNextAlarmInfo.getTriggerTime()
+ - TimeUnit.HOURS.toMillis(ALARM_VISIBILITY_HOURS);
+ if (triggerAt > 0) {
+ mAlarmManager.setExact(AlarmManager.RTC, triggerAt, "lock_screen_next_alarm",
+ mUpdateNextAlarm, mHandler);
+ }
}
}
updateNextAlarm();
@@ -560,4 +606,82 @@
SystemUIAppComponentFactoryBase.ContextAvailableCallback callback) {
mContextAvailableCallback = callback;
}
+
+ private void enableWeatherUpdates() {
+ mWeatherClient = new OmniJawsClient(getContext());
+ mWeatherClient.addObserver(this);
+ queryAndUpdateWeather();
+ }
+
+ private void disableWeatherUpdates() {
+ if (mWeatherClient != null) {
+ mWeatherClient.removeObserver(this);
+ }
+ }
+
+ @Override
+ public void weatherError(int errorReason) {
+ // since this is shown in ambient and lock screen
+ // it would look bad to show every error since the
+ // screen-on revovery of the service had no chance
+ // to run fast enough
+ // so only show the disabled state
+ if (errorReason == OmniJawsClient.EXTRA_ERROR_DISABLED) {
+ mWeatherData = null;
+ notifyChange();
+ }
+ }
+
+ @Override
+ public void weatherUpdated() {
+ queryAndUpdateWeather();
+ }
+
+ @Override
+ public void updateSettings() {
+ queryAndUpdateWeather();
+ }
+
+ private void queryAndUpdateWeather() {
+ if (mWeatherClient != null) {
+ mWeatherClient.queryWeather();
+ mWeatherData = mWeatherClient.getWeatherInfo();
+ notifyChange();
+ }
+ }
+
+ @Override
+ public void onConsolidatedPolicyChanged(NotificationManager.Policy policy) {
+ notifyChange();
+ }
+
+ private boolean zenAllowsAlarm() {
+ int zen = mZenModeController.getZen();
+ if (zen == Settings.Global.ZEN_MODE_OFF) {
+ return true;
+ }
+ if (zen == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ return false;
+ }
+ if (zen == Settings.Global.ZEN_MODE_ALARMS) {
+ return true;
+ }
+ boolean allowAlarms = (mZenModeController.getConsolidatedPolicy().priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_ALARMS) != 0;
+ return allowAlarms;
+ }
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ mShowWeatherSlice = Settings.System.getIntForUser(mContentResolver,
+ OmniSettings.OMNI_LOCKSCREEN_WEATHER_ENABLED,
+ 0, UserHandle.USER_CURRENT) != 0;
+ mShowAlarmSlice = Settings.System.getIntForUser(mContentResolver,
+ OmniSettings.OMNI_LOCKSCREEN_ALARM_ENABLED,
+ 1, UserHandle.USER_CURRENT) != 0;
+ mShowDndSlice = Settings.System.getIntForUser(mContentResolver,
+ OmniSettings.OMNI_LOCKSCREEN_DND_ENABLED,
+ 0, UserHandle.USER_CURRENT) != 0;
+ notifyChange();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
index e8ded03..74bdfa1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/log/SessionTracker.java
@@ -181,6 +181,20 @@
mKeyguardSessionStarted = true;
startSession(SESSION_KEYGUARD);
}
+
+ @Override
+ public void onStartedWakingUp() {
+ boolean wasSessionStarted = mKeyguardSessionStarted;
+ boolean keyguardShowing = mKeyguardStateController.isShowing();
+
+ // pressed power button BEFORE onKeyguardShowingChanged came
+ // left us with a dangling session start that wont go away
+ // until the next sleep cycle
+ if (wasSessionStarted && !keyguardShowing) {
+ endSession(SESSION_KEYGUARD, SessionUiEvent.KEYGUARD_SESSION_END_GOING_TO_SLEEP);
+ mKeyguardSessionStarted = false;
+ }
+ }
};
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index b1719107..2aea3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -52,8 +52,10 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
+import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.ArraySet;
+import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
@@ -109,6 +111,8 @@
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import kotlinx.coroutines.Job;
import java.io.PrintWriter;
@@ -364,6 +368,9 @@
private final Consumer<Boolean> mOnIsInPipStateChangedListener =
(isInPip) -> mIsInPip = isInPip;
+ // omni additions start
+ private int mEdgeHeight;
+
private final Consumer<Region> mDesktopCornersChangedListener =
(desktopExcludeRegion) -> mDesktopModeExcludeRegion.set(desktopExcludeRegion);
@@ -586,6 +593,7 @@
mNonLinearFactor = getDimenFloat(res,
com.android.internal.R.dimen.back_progress_non_linear_factor);
updateBackAnimationThresholds();
+ updateEdgeHeightValue();
mBackgroundExecutor.execute(this::disableNavBarVirtualKeyHapticFeedback);
}
@@ -607,6 +615,25 @@
}
}
+ private void updateEdgeHeightValue() {
+ int edgeHeightSetting = Settings.System.getIntForUser(mContext.getContentResolver(),
+ OmniSettings.OMNI_BACK_GESTURE_HEIGHT, 0, UserHandle.USER_CURRENT);
+ // edgeHeigthSettings cant be range 0 - 3
+ // 0 means full height
+ // 1 measns half of the screen
+ // 2 means lower third of the screen
+ // 3 means lower sicth of the screen
+ if (edgeHeightSetting == 0) {
+ mEdgeHeight = mDisplaySize.y;
+ } else if (edgeHeightSetting == 1) {
+ mEdgeHeight = mDisplaySize.y / 2;
+ } else if (edgeHeightSetting == 2) {
+ mEdgeHeight = mDisplaySize.y / 3;
+ } else {
+ mEdgeHeight = mDisplaySize.y / 6;
+ }
+ }
+
private void updateTopActivity() {
if (edgebackGestureHandlerGetRunningTasksBackground()) {
mBackgroundExecutor.execute(() -> updateTopActivityPackageName());
@@ -937,6 +964,12 @@
if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
return false;
}
+ if (mEdgeHeight != 0) {
+ if (y < (mDisplaySize.y - mBottomGestureHeight - mEdgeHeight)) {
+ return false;
+ }
+ }
+
// If the point is way too far (twice the margin), it is
// not interesting to us for logging purposes, nor we
// should process it. Simply return false and keep
@@ -1258,6 +1291,7 @@
mEdgeBackPlugin.setDisplaySize(mDisplaySize);
}
updateBackAnimationThresholds();
+ updateEdgeHeightValue();
}
private void updateBackAnimationThresholds() {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
index c895732..10e322f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
@@ -165,6 +165,8 @@
import dagger.Lazy;
+import org.omnirom.omnilib.utils.TaskUtils;
+
import java.io.PrintWriter;
import java.util.Locale;
import java.util.Map;
@@ -1332,6 +1334,10 @@
ButtonDispatcher backButton = mView.getBackButton();
backButton.setNavBarButtonClickLogger(mNavBarButtonClickLogger);
+ ButtonDispatcher homeHandleButton = mView.getHomeHandle();
+ homeHandleButton.setLongClickable(true);
+ homeHandleButton.setOnLongClickListener(this::onHomeHandleLongClick);
+
reconfigureHomeLongClick();
ButtonDispatcher accessibilityButton = mView.getAccessibilityButton();
@@ -1933,6 +1939,10 @@
updateButtonLocation(
region, touchRegionCache, mView.getAccessibilityButton(), inScreenSpace,
useNearestRegion);
+ updateButtonLocation(region, mView.getKeyButtonViewById(R.id.dpad_left), inScreenSpace);
+ updateButtonLocation(region, mView.getKeyButtonViewById(R.id.dpad_right), inScreenSpace);
+ updateButtonLocation(
+ region, touchRegionCache, mView.getHomeHandle(), inScreenSpace, useNearestRegion);
if (mView.getFloatingRotationButton().isVisible()) {
// Note: this button is floating so the nearest region doesn't apply
updateButtonLocation(
@@ -2099,4 +2109,9 @@
return false;
}
};
+
+ private boolean onHomeHandleLongClick(View v) {
+ TaskUtils.toggleLastApp(mContext, mUserTracker.getUserId());
+ return true;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
index 96b730c..e8a228f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarInflaterView.java
@@ -23,6 +23,8 @@
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Icon;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -41,15 +43,20 @@
import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.navigationbar.views.buttons.ReverseLinearLayout;
import com.android.systemui.navigationbar.views.buttons.ReverseLinearLayout.ReverseRelativeLayout;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.res.R;
import com.android.systemui.shared.system.QuickStepContract;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.Objects;
-public class NavigationBarInflaterView extends FrameLayout {
+public class NavigationBarInflaterView extends FrameLayout
+ implements OmniSettingsService.OmniSettingsObserver {
+
private static final String TAG = "NavBarInflater";
public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
@@ -157,12 +164,21 @@
}
protected String getDefaultLayout() {
- final int defaultResource = QuickStepContract.isGesturalMode(mNavBarMode)
- ? R.string.config_navBarLayoutHandle
- : mOverviewProxyService.shouldShowSwipeUpUI()
- ? R.string.config_navBarLayoutQuickstep
- : R.string.config_navBarLayout;
- return getContext().getString(defaultResource);
+ if (QuickStepContract.isGesturalMode(mNavBarMode)) {
+ String navbarLayout = getContext().getString(showDpadArrowKeys()
+ ? R.string.config_navBarLayoutHandleArrows
+ : R.string.config_navBarLayoutHandle);
+ if (hideGestureHandle()) {
+ return navbarLayout.replace(HOME_HANDLE, NAVSPACE);
+ } else {
+ return navbarLayout;
+ }
+ } else {
+ final int defaultResource = mOverviewProxyService.shouldShowSwipeUpUI()
+ ? R.string.config_navBarLayoutQuickstep
+ : R.string.config_navBarLayout;
+ return getContext().getString(defaultResource);
+ }
}
private void onNavigationModeChanged(int mode) {
@@ -172,9 +188,21 @@
@Override
protected void onDetachedFromWindow() {
Dependency.get(NavigationModeController.class).removeListener(mListener);
+ Dependency.get(OmniSettingsService.class).removeObserver(this);
super.onDetachedFromWindow();
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_NAVIGATION_BAR_ARROW_KEYS);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_GESTURE_HANDLE_HIDE);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_GESTURE_HANDLE_SMALL);
+ }
+
public void onLikelyDefaultLayoutChange() {
// Reevaluate new layout
final String newValue = getDefaultLayout();
@@ -184,6 +212,12 @@
}
}
+ private void onForceDefaultLayoutChange() {
+ final String newValue = getDefaultLayout();
+ clearViews();
+ inflateLayout(newValue);
+ }
+
public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) {
mButtonDispatchers = buttonDispatchers;
clearDispatcherViews();
@@ -402,7 +436,7 @@
} else if (CONTEXTUAL.equals(button)) {
v = inflater.inflate(R.layout.contextual, parent, false);
} else if (HOME_HANDLE.equals(button)) {
- v = inflater.inflate(R.layout.home_handle, parent, false);
+ v = inflater.inflate(isSmallGestureHandle() ? R.layout.home_handle_small : R.layout.home_handle, parent, false);
} else if (IME_SWITCHER.equals(button)) {
v = inflater.inflate(R.layout.ime_switcher, parent, false);
} else if (button.startsWith(KEY)) {
@@ -489,7 +523,9 @@
private void clearAllChildren(ViewGroup group) {
for (int i = 0; i < group.getChildCount(); i++) {
- ((ViewGroup) group.getChildAt(i)).removeAllViews();
+ if (group.getChildAt(i).getId() != R.id.dpad_group) {
+ ((ViewGroup) group.getChildAt(i)).removeAllViews();
+ }
}
}
@@ -497,6 +533,26 @@
return dp * context.getResources().getDisplayMetrics().density;
}
+ private boolean showDpadArrowKeys() {
+ return Settings.System.getIntForUser(getContext().getContentResolver(),
+ OmniSettings.OMNI_NAVIGATION_BAR_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
+ private boolean hideGestureHandle() {
+ return Settings.System.getIntForUser(getContext().getContentResolver(),
+ OmniSettings.OMNI_GESTURE_HANDLE_HIDE, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
+ private boolean isSmallGestureHandle() {
+ return Settings.System.getIntForUser(getContext().getContentResolver(),
+ OmniSettings.OMNI_GESTURE_HANDLE_SMALL, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ onForceDefaultLayoutChange();
+ }
+
public void dump(PrintWriter pw) {
pw.println("NavigationBarInflaterView");
pw.println(" mCurrentLayout: " + mCurrentLayout);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarTransitions.java
index 251745d..735337d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarTransitions.java
@@ -191,6 +191,7 @@
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
mView.getRotationButtonController().setDarkIntensity(darkIntensity);
+ mView.setDpadDarkIntensity(darkIntensity);
for (DarkIntensityListener listener : mDarkIntensityListeners) {
listener.onDarkIntensity(darkIntensity);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
index c4abcd2..2284eef 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBarView.java
@@ -39,6 +39,8 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -63,6 +65,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
import com.android.systemui.Gefingerpoken;
+import com.android.systemui.Dependency;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.ScreenPinningNotify;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
@@ -71,7 +74,9 @@
import com.android.systemui.navigationbar.views.buttons.ContextualButtonGroup;
import com.android.systemui.navigationbar.views.buttons.DeadZone;
import com.android.systemui.navigationbar.views.buttons.KeyButtonDrawable;
+import com.android.systemui.navigationbar.views.buttons.KeyButtonView;
import com.android.systemui.navigationbar.views.buttons.NearestTouchFrame;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.recents.Recents;
import com.android.systemui.res.R;
import com.android.systemui.settings.DisplayTracker;
@@ -87,6 +92,8 @@
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.PrintWriter;
import java.util.Map;
import java.util.Optional;
@@ -94,7 +101,8 @@
import java.util.function.Consumer;
/** */
-public class NavigationBarView extends FrameLayout {
+public class NavigationBarView extends FrameLayout implements
+ OmniSettingsService.OmniSettingsObserver {
final static boolean DEBUG = false;
final static String TAG = "NavBarView";
@@ -117,6 +125,8 @@
private int mNavBarMode;
private boolean mImeDrawsImeNavBar;
+ private KeyButtonDrawable mArrowLeftIcon;
+ private KeyButtonDrawable mArrowRightIcon;
private KeyButtonDrawable mBackIcon;
private KeyButtonDrawable mHomeDefaultIcon;
private KeyButtonDrawable mRecentIcon;
@@ -142,6 +152,7 @@
private boolean mInCarMode = false;
private boolean mDockedStackExists;
private boolean mScreenOn = true;
+ private boolean mShowDpadArrowKeys;
private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
private final ContextualButtonGroup mContextualButtonGroup;
@@ -454,6 +465,10 @@
return mShowSwipeUpUi && isOverviewEnabled();
}
+ public KeyButtonView getKeyButtonViewById(int id) {
+ return (KeyButtonView) getCurrentView().findViewById(id);
+ }
+
private void reloadNavIcons() {
updateIcons(Configuration.EMPTY);
}
@@ -474,6 +489,8 @@
if (orientationChange || densityChange || dirChange) {
mBackIcon = getBackDrawable();
}
+ mArrowLeftIcon = getDrawable(R.drawable.ic_navbar_chevron_left);
+ mArrowRightIcon = getDrawable(R.drawable.ic_navbar_chevron_right);
}
/**
@@ -600,12 +617,23 @@
updateRecentsIcon();
+ if (mShowDpadArrowKeys) {
+ getKeyButtonViewById(R.id.dpad_left).setImageDrawable(mArrowLeftIcon);
+ getKeyButtonViewById(R.id.dpad_right).setImageDrawable(mArrowRightIcon);
+ updateDpadKeys();
+ }
+
// Update IME button visibility, a11y and rotate button always overrides the appearance
boolean disableImeSwitcher =
(mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN) == 0
|| isImeRenderingNavButtons();
mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, !disableImeSwitcher);
+ // right arrow overrules ime in 3 button mode cause there is not enough space
+ if (QuickStepContract.isLegacyMode(mNavBarMode) && mShowDpadArrowKeys) {
+ mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, false);
+ }
+
mBarTransitions.reapplyDarkIntensity();
boolean disableHome = isGesturalMode(mNavBarMode)
@@ -1082,6 +1110,8 @@
}
updateNavButtonIcons();
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_NAVIGATION_BAR_ARROW_KEYS);
}
@Override
@@ -1094,6 +1124,7 @@
mFloatingRotationButton.hide();
mRotationButtonController.unregisterListeners();
}
+ Dependency.get(OmniSettingsService.class).removeObserver(this);
}
void dump(PrintWriter pw) {
@@ -1202,4 +1233,28 @@
interface UpdateActiveTouchRegionsCallback {
void update();
}
+
+ private void updateDpadKeys() {
+ final int visibility = mShowDpadArrowKeys && (mNavigationIconHints
+ & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 ? View.VISIBLE : View.GONE;
+ getKeyButtonViewById(R.id.dpad_left).setVisibility(visibility);
+ getKeyButtonViewById(R.id.dpad_right).setVisibility(visibility);
+ }
+ public void setDpadDarkIntensity(float darkIntensity) {
+ if (mShowDpadArrowKeys) {
+ getKeyButtonViewById(R.id.dpad_left).setDarkIntensity(darkIntensity);
+ getKeyButtonViewById(R.id.dpad_right).setDarkIntensity(darkIntensity);
+ }
+ }
+ private boolean showDpadArrowKeys() {
+ return Settings.System.getIntForUser(getContext().getContentResolver(),
+ OmniSettings.OMNI_NAVIGATION_BAR_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ mShowDpadArrowKeys = showDpadArrowKeys();
+ updateNavButtonIcons();
+ notifyActiveTouchRegions();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
index 111a2d4..74fffbd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/buttons/KeyButtonView.java
@@ -69,6 +69,9 @@
public class KeyButtonView extends ImageView implements ButtonInterface {
private static final String TAG = KeyButtonView.class.getSimpleName();
+ public static final int CURSOR_REPEAT_FLAGS = KeyEvent.FLAG_SOFT_KEYBOARD
+ | KeyEvent.FLAG_KEEP_TOUCH_MODE;
+
private final boolean mPlaySounds;
private final UiEventLogger mUiEventLogger;
private int mContentDescriptionRes;
@@ -134,7 +137,13 @@
public void run() {
if (isPressed()) {
// Log.d("KeyButtonView", "longpressed: " + this);
- if (isLongClickable()) {
+ if (mCode == KeyEvent.KEYCODE_DPAD_LEFT || mCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+ sendEvent(KeyEvent.ACTION_UP, CURSOR_REPEAT_FLAGS,
+ System.currentTimeMillis(), false);
+ sendEvent(KeyEvent.ACTION_DOWN, CURSOR_REPEAT_FLAGS,
+ System.currentTimeMillis(), false);
+ postDelayed(mCheckLongPress, ViewConfiguration.getKeyRepeatDelay());
+ } else if (isLongClickable()) {
// Just an old-fashioned ImageView
performLongClick();
mLongClicked = true;
@@ -301,7 +310,10 @@
mTouchDownX = (int) ev.getX();
mTouchDownY = (int) ev.getY();
- if (mCode != KEYCODE_UNKNOWN) {
+ if (mCode == KeyEvent.KEYCODE_DPAD_LEFT || mCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
+ sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_VIRTUAL_HARD_KEY
+ | KeyEvent.FLAG_KEEP_TOUCH_MODE, mDownTime, false);
+ } else if (mCode != KEYCODE_UNKNOWN) {
sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);
} else {
// Provide the same haptic feedback that the system offers for virtual keys.
@@ -438,6 +450,10 @@
}
private void sendEvent(int action, int flags, long when) {
+ sendEvent(action, flags, when, true);
+ }
+
+ private void sendEvent(int action, int flags, long when, boolean applyDefaultFlags) {
mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_NAV_BUTTON_EVENT)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(mCode)
@@ -448,9 +464,12 @@
Log.i(TAG, "Back button event: " + KeyEvent.actionToString(action));
}
final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
+ if (applyDefaultFlags) {
+ flags |= KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY;
+ }
final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
- flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ flags,
InputDevice.SOURCE_KEYBOARD);
int displayId = INVALID_DISPLAY;
diff --git a/packages/SystemUI/src/com/android/systemui/omni/CPUInfoManager.java b/packages/SystemUI/src/com/android/systemui/omni/CPUInfoManager.java
new file mode 100644
index 0000000..2fa69fd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/omni/CPUInfoManager.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 The OmniROM 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.omni;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.systemui.res.R;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.CoreStartable;
+import com.android.systemui.Dependency;
+
+import javax.inject.Inject;
+
+@SysUISingleton
+public class CPUInfoManager implements CoreStartable, OmniSettingsService.OmniSettingsObserver {
+ private final String TAG = "CPUInfoManager";
+ private final String OMNI_SHOW_CPU_OVERLAY = "show_cpu_overlay";
+ private Context mContext;
+
+ @Inject
+ public CPUInfoManager(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void onBootCompleted() {
+ Log.d(TAG, "CPUInfoManager onBootCompleted");
+ Dependency.get(OmniSettingsService.class).addIntObserver(this, OMNI_SHOW_CPU_OVERLAY);
+ }
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ if (OMNI_SHOW_CPU_OVERLAY.equals(key)) {
+ try {
+ Intent cpuinfo = new Intent(mContext, com.android.systemui.omni.CPUInfoService.class);
+ if (newValue != null && newValue == 1) {
+ mContext.startService(cpuinfo);
+ } else {
+ mContext.stopService(cpuinfo);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "CPUInfoManager update ", e);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/omni/CPUInfoService.java b/packages/SystemUI/src/com/android/systemui/omni/CPUInfoService.java
new file mode 100644
index 0000000..93b1eeb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/omni/CPUInfoService.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2017 The OmniROM 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.omni;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
+import android.util.Log;
+
+import com.android.systemui.res.R;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.StringBuffer;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CPUInfoService extends Service {
+ private View mView;
+ private Thread mCurCPUThread;
+ private final String TAG = "CPUInfoService";
+ private final boolean DEBUG = false;
+ private int mNumCpus = 2;
+ private String[] mCpu = null;
+ private String[] mCurrFreq = null;
+ private String[] mCurrGov = null;
+
+ private int CPU_TEMP_DIVIDER = 1;
+ private String CPU_TEMP_SENSOR = "";
+ private String DISPLAY_CPUS = "";
+ private boolean mCpuTempAvail;
+ private int mTextHeight;
+
+ private static final String NUM_OF_CPUS_PATH = "/sys/devices/system/cpu/present";
+ private static final String CURRENT_CPU = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq";
+ private static final String CPU_ROOT = "/sys/devices/system/cpu/cpu";
+ private static final String CPU_CUR_TAIL = "/cpufreq/scaling_cur_freq";
+ private static final String CPU_GOV_TAIL = "/cpufreq/scaling_governor";
+
+ private IDreamManager mDreamManager;
+
+ private class CPUView extends View {
+ private Paint mOnlinePaint;
+ private Paint mOfflinePaint;
+ private float mAscent;
+ private int mFH;
+ private int mMaxWidth;
+ private int mExtraPaddingTop;
+
+ private int mNeededWidth;
+ private int mNeededHeight;
+ private String mCpuTemp;
+
+ private boolean mDataAvail;
+
+ private Handler mCurCPUHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ if(msg.obj==null){
+ return;
+ }
+ if(msg.what==1){
+ String msgData = (String) msg.obj;
+ try {
+ if (DEBUG) Log.d(TAG, "msgData = " + msgData);
+ String[] parts=msgData.split(";");
+ mCpuTemp=parts[0];
+
+ String[] cpuParts=parts[1].split("\\|");
+ for(int i=0; i<cpuParts.length; i++){
+ String cpuInfo=cpuParts[i];
+ String cpuInfoParts[]=cpuInfo.split(":");
+ if(cpuInfoParts.length==3){
+ mCurrFreq[i]=cpuInfoParts[1];
+ mCurrGov[i]=cpuInfoParts[2];
+ } else {
+ mCurrFreq[i]="0";
+ mCurrGov[i]="";
+ }
+ }
+ mDataAvail = true;
+ updateDisplay();
+ } catch(ArrayIndexOutOfBoundsException e) {
+ Log.e(TAG, "illegal data " + msgData);
+ }
+ }
+ }
+ };
+
+ CPUView(Context c) {
+ super(c);
+ float density = c.getResources().getDisplayMetrics().density;
+ int paddingPx = Math.round(5 * density);
+ setPadding(paddingPx, paddingPx, paddingPx, paddingPx);
+ setBackgroundColor(Color.argb(0x60, 0, 0, 0));
+
+ final int textSize = mTextHeight;
+ mExtraPaddingTop = c.getResources().getDimensionPixelSize(R.dimen.status_bar_height);
+
+ Typeface typeface = Typeface.create("monospace", Typeface.NORMAL);
+
+ mOnlinePaint = new Paint();
+ mOnlinePaint.setTypeface(typeface);
+ mOnlinePaint.setAntiAlias(true);
+ mOnlinePaint.setTextSize(textSize);
+ mOnlinePaint.setColor(Color.WHITE);
+ mOnlinePaint.setShadowLayer(5.0f, 0.0f, 0.0f, Color.BLACK);
+
+ mOfflinePaint = new Paint();
+ mOfflinePaint.setTypeface(typeface);
+ mOfflinePaint.setAntiAlias(true);
+ mOfflinePaint.setTextSize(textSize);
+ mOfflinePaint.setColor(Color.RED);
+
+ mAscent = mOnlinePaint.ascent();
+ float descent = mOnlinePaint.descent();
+ mFH = (int)(descent - mAscent + .5f);
+
+ final String maxWidthStr="cpuX: interactive 00000000";
+ mMaxWidth = (int)mOnlinePaint.measureText(maxWidthStr);
+
+ updateDisplay();
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mCurCPUHandler.removeMessages(1);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(resolveSize(mNeededWidth, widthMeasureSpec),
+ resolveSize(mNeededHeight, heightMeasureSpec));
+ }
+
+ private String getCPUInfoString(int i) {
+ String cpu=mCpu[i];
+ String freq=mCurrFreq[i];
+ String gov=mCurrGov[i];
+ return "cpu" + cpu + ": " + gov + " " + String.format("%8s", toMHz(freq));
+ }
+
+ private String getCpuTemp(String cpuTemp) {
+ if (CPU_TEMP_DIVIDER > 1) {
+ return String.format("%s",
+ Integer.parseInt(cpuTemp) / CPU_TEMP_DIVIDER);
+ } else {
+ return cpuTemp;
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (!mDataAvail) {
+ return;
+ }
+
+ final int W = mNeededWidth;
+ final int RIGHT = getWidth()-1;
+
+ int x = RIGHT - mPaddingRight;
+ int top = mExtraPaddingTop + mPaddingTop + 2;
+ int bottom = mExtraPaddingTop + mPaddingTop + mFH - 2;
+
+ int y = mExtraPaddingTop + mPaddingTop - (int)mAscent;
+
+ if(!mCpuTemp.equals("0")) {
+ canvas.drawText("Temp: " + getCpuTemp(mCpuTemp) + "°C",
+ RIGHT-mPaddingRight-mMaxWidth, y-1, mOnlinePaint);
+ y += mFH;
+ }
+
+ for(int i=0; i<mCurrFreq.length; i++){
+ String s=getCPUInfoString(i);
+ String freq=mCurrFreq[i];
+ if(!freq.equals("0")){
+ canvas.drawText(s, RIGHT-mPaddingRight-mMaxWidth,
+ y-1, mOnlinePaint);
+ } else {
+ canvas.drawText("cpu" + mCpu[i] + ": offline", RIGHT-mPaddingRight-mMaxWidth,
+ y-1, mOfflinePaint);
+ }
+ y += mFH;
+ }
+ }
+
+ void updateDisplay() {
+ if (!mDataAvail) {
+ return;
+ }
+ final int NW = mNumCpus;
+
+ int neededWidth = mPaddingLeft + mPaddingRight + mMaxWidth;
+ int neededHeight = mExtraPaddingTop + mPaddingTop + mPaddingBottom + (mFH*((mCpuTempAvail?1:0)+NW));
+ if (neededWidth != mNeededWidth || neededHeight != mNeededHeight) {
+ mNeededWidth = neededWidth;
+ mNeededHeight = neededHeight;
+ requestLayout();
+ } else {
+ invalidate();
+ }
+ }
+
+ private String toMHz(String mhzString) {
+ return new StringBuilder().append(Integer.valueOf(mhzString) / 1000).append(" MHz").toString();
+ }
+
+ public Handler getHandler(){
+ return mCurCPUHandler;
+ }
+ }
+
+ protected class CurCPUThread extends Thread {
+ private boolean mInterrupt = false;
+ private Handler mHandler;
+
+ public CurCPUThread(Handler handler, int numCpus){
+ mHandler=handler;
+ mNumCpus = numCpus;
+ }
+
+ public void interrupt() {
+ mInterrupt = true;
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (!mInterrupt) {
+ sleep(500);
+ StringBuffer sb=new StringBuffer();
+ String cpuTemp = CPUInfoService.readOneLine(CPU_TEMP_SENSOR);
+ sb.append(cpuTemp == null ? "0" : cpuTemp);
+ sb.append(";");
+
+ for(int i=0; i<mNumCpus; i++) {
+ final String currCpu = mCpu[i];
+ final String freqFile=CPU_ROOT + mCpu[i] + CPU_CUR_TAIL;
+ String currFreq = CPUInfoService.readOneLine(freqFile);
+ final String govFile=CPU_ROOT + mCpu[i] + CPU_GOV_TAIL;
+ String currGov = CPUInfoService.readOneLine(govFile);
+
+ if(currFreq==null){
+ currFreq="0";
+ currGov="";
+ }
+
+ sb.append(currCpu+":"+currFreq+":"+currGov+"|");
+ }
+ sb.deleteCharAt(sb.length()-1);
+ mHandler.sendMessage(mHandler.obtainMessage(1, sb.toString()));
+ }
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.d(TAG, "CPUInfoService onCreate");
+
+ CPU_TEMP_DIVIDER = getResources().getInteger(R.integer.config_cpuTempDivider);
+ CPU_TEMP_SENSOR = getResources().getString(R.string.config_cpuTempSensor);
+ DISPLAY_CPUS = getResources().getString(R.string.config_displayCpus);
+ mTextHeight = getResources().getDimensionPixelSize(R.dimen.cpu_info_text_height);
+
+ mNumCpus = getCpus(DISPLAY_CPUS);
+ mCurrFreq = new String[mNumCpus];
+ mCurrGov = new String[mNumCpus];
+
+ mCpuTempAvail = readOneLine(CPU_TEMP_SENSOR) != null;
+
+ mView = new CPUView(this);
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
+ PixelFormat.TRANSLUCENT);
+ params.gravity = Gravity.RIGHT | Gravity.TOP;
+ params.setTitle("CPU Info");
+ // we force a unified top margin in mExtraPaddingTop under status bar
+ params.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ startThread();
+
+ mDreamManager = IDreamManager.Stub.asInterface(
+ ServiceManager.checkService(DreamService.DREAM_SERVICE));
+ IntentFilter screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
+ screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ registerReceiver(mScreenStateReceiver, screenStateFilter);
+
+ WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
+ wm.addView(mView, params);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(TAG, "CPUInfoService onDestroy");
+ stopThread();
+ ((WindowManager)getSystemService(WINDOW_SERVICE)).removeView(mView);
+ mView = null;
+ unregisterReceiver(mScreenStateReceiver);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private static String readOneLine(String fname) {
+ BufferedReader br;
+ String line = null;
+ try {
+ br = new BufferedReader(new FileReader(fname), 512);
+ try {
+ line = br.readLine();
+ } finally {
+ br.close();
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return line;
+ }
+
+ private int getCpus(String displayCpus) {
+ int numOfCpu = 1;
+ String[] cpuList = null;
+
+ if (displayCpus != null) {
+ cpuList = displayCpus.split(",");
+ if (cpuList.length > 0) {
+ numOfCpu = cpuList.length;
+ mCpu = new String[numOfCpu];
+
+ for (int i = 0; i < numOfCpu; i++) {
+ try {
+ int cpu = Integer.parseInt(cpuList[i]);
+ mCpu[i] = cpuList[i];
+ } catch (NumberFormatException ex) {
+ // derped overlay
+ return getCpus(null);
+ }
+ }
+ } else {
+ // derped overlay
+ return getCpus(null);
+ }
+ } else {
+ // empty overlay, take all cores
+ String numOfCpus = readOneLine(NUM_OF_CPUS_PATH);
+ cpuList = numOfCpus.split("-");
+ if (cpuList.length > 1) {
+ try {
+ int cpuStart = Integer.parseInt(cpuList[0]);
+ int cpuEnd = Integer.parseInt(cpuList[1]);
+
+ numOfCpu = cpuEnd - cpuStart + 1;
+
+ if (numOfCpu < 0)
+ numOfCpu = 1;
+ } catch (NumberFormatException ex) {
+ numOfCpu = 1;
+ }
+ }
+
+ mCpu = new String[numOfCpu];
+ for (int i = 0; i < numOfCpu; i++)
+ {
+ mCpu[i] = String.valueOf(i);
+ }
+ }
+ return numOfCpu;
+ }
+
+ private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
+ if (DEBUG) Log.d(TAG, "ACTION_SCREEN_ON " + isDozeMode());
+ if (!isDozeMode()) {
+ startThread();
+ mView.setVisibility(View.VISIBLE);
+ }
+ } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+ if (DEBUG) Log.d(TAG, "ACTION_SCREEN_OFF");
+ mView.setVisibility(View.GONE);
+ stopThread();
+ }
+ }
+ };
+
+ private boolean isDozeMode() {
+ try {
+ if (mDreamManager != null && mDreamManager.isDozing()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ return false;
+ }
+
+ private void startThread() {
+ if (DEBUG) Log.d(TAG, "started CurCPUThread");
+ mCurCPUThread = new CurCPUThread(mView.getHandler(), mNumCpus);
+ mCurCPUThread.start();
+ }
+
+ private void stopThread() {
+ if (mCurCPUThread != null && mCurCPUThread.isAlive()) {
+ if (DEBUG) Log.d(TAG, "stopping CurCPUThread");
+ mCurCPUThread.interrupt();
+ try {
+ mCurCPUThread.join();
+ } catch (InterruptedException e) {
+ }
+ }
+ mCurCPUThread = null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsService.java b/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsService.java
new file mode 100644
index 0000000..239db49
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsService.java
@@ -0,0 +1,28 @@
+/*
+ * 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.omni;
+
+public abstract class OmniSettingsService {
+
+ public abstract void addStringObserver(OmniSettingsObserver observer, String... keys);
+ public abstract void addIntObserver(OmniSettingsObserver observer, String... keys);
+ public abstract void removeObserver(OmniSettingsObserver observer);
+ public abstract void destroy();
+
+ public interface OmniSettingsObserver {
+ default void onStringSettingChanged(String key, String newValue) {}
+ default void onIntSettingChanged(String key, Integer newValue) {}
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsServiceImpl.java b/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsServiceImpl.java
new file mode 100644
index 0000000..a1e1bd6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/omni/OmniSettingsServiceImpl.java
@@ -0,0 +1,213 @@
+/*
+ * 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
+ */
+package com.android.systemui.omni;
+
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.settings.UserTracker;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+/**
+ */
+@SysUISingleton
+public class OmniSettingsServiceImpl extends OmniSettingsService {
+ private static final String TAG = "OmniSettingsService";
+ private final Observer mObserver = new Observer();
+ // Map of Uris we listen on to their settings keys.
+ private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
+ // Map of settings keys to the listener.
+ private final HashMap<String, Set<OmniSettingsObserver>> mObserverLookup = new HashMap<>();
+ private final HashSet<String> mStringSettings = new HashSet<>();
+ private final HashSet<String> mIntSettings = new HashSet<>();
+ private final Context mContext;
+ private ContentResolver mContentResolver;
+ private int mCurrentUser;
+ private UserTracker.Callback mCurrentUserTracker;
+ private UserTracker mUserTracker;
+
+ /**
+ */
+ @Inject
+ public OmniSettingsServiceImpl(Context context, @Main Handler mainHandler,
+ UserTracker userTracker) {
+ mContext = context;
+ mContentResolver = mContext.getContentResolver();
+
+ mUserTracker = userTracker;
+ mCurrentUser = mUserTracker.getUserId();
+ mCurrentUserTracker = new UserTracker.Callback() {
+ @Override
+ public void onUserChanged(int newUser, Context userContext) {
+ mCurrentUser = newUser;
+ reloadAll();
+ reregisterAll();
+ }
+ };
+ mUserTracker.addCallback(mCurrentUserTracker,
+ new HandlerExecutor(mainHandler));
+ }
+
+ @Override
+ public void destroy() {
+ mUserTracker.removeCallback(mCurrentUserTracker);
+ }
+
+ @Override
+ public void addStringObserver(OmniSettingsObserver observer, String... keys) {
+ for (String key : keys) {
+ addStringObserver(observer, key);
+ }
+ }
+
+ @Override
+ public void addIntObserver(OmniSettingsObserver observer, String... keys) {
+ for (String key : keys) {
+ addIntObserver(observer, key);
+ }
+ }
+
+ private void addObserver(OmniSettingsObserver observer, String key) {
+ if (!mObserverLookup.containsKey(key)) {
+ mObserverLookup.put(key, new ArraySet<OmniSettingsObserver>());
+ }
+ if (!mObserverLookup.get(key).contains(observer)) {
+ mObserverLookup.get(key).add(observer);
+ }
+ Uri uri = Settings.System.getUriFor(key);
+ if (!mListeningUris.containsKey(uri)) {
+ mListeningUris.put(uri, key);
+ mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
+ }
+ }
+
+ private void addStringObserver(OmniSettingsObserver observer, String key) {
+ mStringSettings.add(key);
+ addObserver(observer, key);
+ // Send the first state.
+ String value = Settings.System.getStringForUser(mContentResolver, key, mCurrentUser);
+ observer.onStringSettingChanged(key, value);
+ }
+
+ private void addIntObserver(OmniSettingsObserver observer, String key) {
+ mIntSettings.add(key);
+ addObserver(observer, key);
+ // Send the first state.
+ try {
+ Integer value = Settings.System.getIntForUser(mContentResolver, key, mCurrentUser);
+ observer.onIntSettingChanged(key, value);
+ } catch(Settings.SettingNotFoundException e) {
+ }
+ }
+
+ @Override
+ public void removeObserver(OmniSettingsObserver observer) {
+ for (Set<OmniSettingsObserver> list : mObserverLookup.values()) {
+ list.remove(observer);
+ }
+ }
+
+ protected void reregisterAll() {
+ if (mListeningUris.size() == 0) {
+ return;
+ }
+ mContentResolver.unregisterContentObserver(mObserver);
+ for (Uri uri : mListeningUris.keySet()) {
+ mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
+ }
+ }
+
+ private void reloadSetting(Uri uri) {
+ String key = mListeningUris.get(uri);
+ Set<OmniSettingsObserver> observers = mObserverLookup.get(key);
+ if (observers == null) {
+ return;
+ }
+ if (mStringSettings.contains(key)) {
+ String value = Settings.System.getStringForUser(mContentResolver, key, mCurrentUser);
+ for (OmniSettingsObserver observer : observers) {
+ observer.onStringSettingChanged(key, value);
+ }
+ }
+ if (mIntSettings.contains(key)) {
+ try {
+ Integer value = Settings.System.getIntForUser(mContentResolver, key, mCurrentUser);
+ for (OmniSettingsObserver observer : observers) {
+ observer.onIntSettingChanged(key, value);
+ }
+ } catch(Settings.SettingNotFoundException e) {
+ }
+ }
+ }
+
+ private void reloadAll() {
+ for (String key : mObserverLookup.keySet()) {
+ if (mStringSettings.contains(key)) {
+ String value = Settings.System.getStringForUser(mContentResolver, key, mCurrentUser);
+ for (OmniSettingsObserver observer : mObserverLookup.get(key)) {
+ observer.onStringSettingChanged(key, value);
+ }
+ }
+ if (mIntSettings.contains(key)) {
+ try {
+ Integer value = Settings.System.getIntForUser(mContentResolver, key, mCurrentUser);
+ for (OmniSettingsObserver observer : mObserverLookup.get(key)) {
+ observer.onIntSettingChanged(key, value);
+ }
+ } catch(Settings.SettingNotFoundException e) {
+ }
+ }
+ }
+ }
+
+ private class Observer extends ContentObserver {
+ public Observer() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange, java.util.Collection<Uri> uris,
+ int flags, int userId) {
+ if (userId == mUserTracker.getUserId()) {
+ for (Uri u : uris) {
+ reloadSetting(u);
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/omni/dagger/OmniModule.java b/packages/SystemUI/src/com/android/systemui/omni/dagger/OmniModule.java
new file mode 100644
index 0000000..6ba05ff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/omni/dagger/OmniModule.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 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.omni.dagger;
+
+import com.android.systemui.omni.OmniSettingsService;
+import com.android.systemui.omni.OmniSettingsServiceImpl;
+
+import com.android.systemui.qs.tiles.AODTile;
+import com.android.systemui.qs.tiles.CaffeineTile;
+import com.android.systemui.qs.tiles.DataSwitchTile;
+import com.android.systemui.qs.tiles.ScreenshotTile;
+
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.StringKey;
+
+
+/** Dagger Module for code in the systemui package. */
+@Module
+public interface OmniModule {
+ /** */
+ @Binds
+ OmniSettingsService provideOmniSettingsService(OmniSettingsServiceImpl impl);
+
+ /** Inject Tiles */
+ @Binds
+ @IntoMap
+ @StringKey(AODTile.TILE_SPEC)
+ public abstract QSTileImpl<?> bindAODTile(AODTile aodTile);
+
+ @Binds
+ @IntoMap
+ @StringKey(CaffeineTile.TILE_SPEC)
+ public abstract QSTileImpl<?> bindCaffeineTile(CaffeineTile caffeineTile);
+
+ @Binds
+ @IntoMap
+ @StringKey(DataSwitchTile.TILE_SPEC)
+ public abstract QSTileImpl<?> bindDataSwitchTile(DataSwitchTile dataSwitchTile);
+
+ @Binds
+ @IntoMap
+ @StringKey(ScreenshotTile.TILE_SPEC)
+ public abstract QSTileImpl<?> bindScreenshotTile(ScreenshotTile screenshotTile);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index ca7b06a..1d9f5b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -641,6 +641,20 @@
return mPages.get(0).mRecords.size();
}
+ @Override
+ public int getResourceColumns() {
+ if (mPages.size() == 0) return TileLayout.NO_MAX_COLUMNS;
+ TileLayout currentPage = mPages.get(getCurrentPageNumber());
+ return currentPage.getResourceColumns();
+ }
+ @Override
+ public void updateSettings() {
+ for (int i = 0; i < mPages.size(); i++) {
+ mPages.get(i).updateSettings();
+ }
+ mDistributeTiles = true;
+ }
+
public void startTileReveal(Set<String> tilesToReveal, final Runnable postAnimation) {
if (shouldNotRunAnimation(tilesToReveal)) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
index 5a872d6..5f35e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java
@@ -86,7 +86,7 @@
private void setBuildText() {
if (mBuildText == null) return;
- if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)) {
+ if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext) && false) {
mBuildText.setText(mContext.getString(
com.android.internal.R.string.bugreport_status,
Build.VERSION.RELEASE_OR_CODENAME,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 602f593..8b449f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -682,7 +682,7 @@
void setColumnRowLayout(boolean withMedia) {
mTileLayout.setMinRows(withMedia ? 2 : 1);
- mTileLayout.setMaxColumns(withMedia ? 2 : 4);
+ mTileLayout.setMaxColumns(withMedia ? mTileLayout.getResourceColumns() / 2 : mTileLayout.getResourceColumns());
placeTileLayoutForScene(withMedia);
}
@@ -843,6 +843,10 @@
int getNumVisibleTiles();
default void setLogger(QSLogger qsLogger) { }
+
+ int getResourceColumns();
+
+ void updateSettings();
}
interface OnConfigurationChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index afb852a..3dd3ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -31,10 +31,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.haptics.qs.QSLongPressEffect;
import com.android.systemui.media.controls.ui.view.MediaHost;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizerController;
@@ -53,6 +55,8 @@
import kotlinx.coroutines.DisposableHandle;
import kotlinx.coroutines.flow.StateFlow;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -70,7 +74,7 @@
* @param <T> Type of QSPanel.
*/
public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewController<T>
- implements Dumpable{
+ implements Dumpable, OmniSettingsService.OmniSettingsObserver {
private static final String TAG = "QSPanelControllerBase";
protected final QSHost mHost;
private final QSCustomizerController mQsCustomizerController;
@@ -82,6 +86,7 @@
private final DumpManager mDumpManager;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
protected boolean mShouldUseSplitNotificationShade;
+ private boolean shouldChangeTiles = false;
@Nullable
private Consumer<Boolean> mMediaVisibilityChangedListener;
@@ -256,6 +261,14 @@
switchTileLayout(true);
mDumpManager.registerDumpable(mView.getDumpableTag(), this);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_TILE_VERTICAL_LAYOUT);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_LAYOUT_COLUMNS);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_LAYOUT_COLUMNS_LANDSCAPE);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_TILE_LABEL_HIDE);
setListening(mLastListening);
}
@@ -283,6 +296,8 @@
mMediaHost.removeVisibilityChangeListener(mMediaHostVisibilityListener);
mDumpManager.unregisterDumpable(mView.getDumpableTag());
+ Dependency.get(OmniSettingsService.class).removeObserver(this);
+ shouldChangeTiles = false;
}
@Nullable
@@ -334,7 +349,7 @@
// If we detected that the existing tiles are different than the requested tiles, clear them
// and add the new tiles.
- if (shouldChangeAll) {
+ if (shouldChangeAll || shouldChangeTiles) {
for (QSPanelControllerBase.TileRecord record : mRecords) {
mView.removeTile(record);
record.tile.removeCallback(record.callback);
@@ -602,6 +617,15 @@
return mView.getBrightnessView();
}
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ if (mView.getTileLayout() != null) {
+ mView.getTileLayout().updateSettings();
+ setTiles();
+ shouldChangeTiles = true;
+ }
+ }
+
/**
* Set a listener to collapse/expand QS.
* @param action
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 168be40..89d5e93 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -28,6 +28,8 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.res.R;
+import org.omnirom.omnilib.utils.OmniUtils;
+
/**
* Version of QSPanel that only shows N Quick Tiles in the QS Header.
*/
@@ -36,13 +38,14 @@
private static final String TAG = "QuickQSPanel";
// A fallback value for max tiles number when setting via Tuner (parseNumTiles)
public static final int TUNER_MAX_TILES_FALLBACK = 6;
+ public static final int DEFAULT_MIN_TILES = 4;
private boolean mDisabledByPolicy;
private int mMaxTiles;
public QuickQSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
- mMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_tiles);
+ mMaxTiles = Math.max(DEFAULT_MIN_TILES, getResources().getInteger(R.integer.quick_qs_panel_max_tiles));
}
@Override
@@ -53,7 +56,7 @@
@Override
public TileLayout getOrCreateTileLayout() {
- QQSSideLabelTileLayout layout = new QQSSideLabelTileLayout(mContext);
+ QQSSideLabelTileLayout layout = new QQSSideLabelTileLayout(mContext,this);
layout.setId(R.id.qqs_tile_layout);
return layout;
}
@@ -90,7 +93,7 @@
}
public void setMaxTiles(int maxTiles) {
- mMaxTiles = maxTiles;
+ mMaxTiles = Math.max(DEFAULT_MIN_TILES, maxTiles);
}
@Override
@@ -171,15 +174,17 @@
static class QQSSideLabelTileLayout extends SideLabelTileLayout {
private boolean mLastSelected;
+ private QuickQSPanel mQSPanel;
- QQSSideLabelTileLayout(Context context) {
+ QQSSideLabelTileLayout(Context context, QuickQSPanel qsPanel) {
super(context, null);
+ mQSPanel = qsPanel;
setClipChildren(false);
setClipToPadding(false);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
setLayoutParams(lp);
- setMaxColumns(4);
+ setMaxColumns(getResourceColumns());
}
@Override
@@ -251,5 +256,17 @@
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
mLastSelected = selected;
}
+
+ @Override
+ public int getResourceColumns() {
+ int columns = getResources().getInteger(R.integer.quick_qs_panel_max_tiles);
+ return OmniUtils.getQuickQSColumnsCount(mContext, columns);
+ }
+
+ @Override
+ public void updateSettings() {
+ mQSPanel.setMaxTiles(getResourceColumns());
+ super.updateSettings();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index bc695bdd4..a86a45b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -40,6 +40,8 @@
import kotlinx.coroutines.flow.StateFlow;
+import org.omnirom.omnilib.utils.OmniUtils;
+
import java.util.ArrayList;
import java.util.List;
@@ -125,6 +127,7 @@
@Override
protected void onConfigurationChanged() {
int newMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_tiles);
+ newMaxTiles = OmniUtils.getQuickQSColumnsCount(getContext(), newMaxTiles);
if (newMaxTiles != mView.getNumQuickTiles()) {
setMaxTiles(newMaxTiles);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index ef44e5f..6979e58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -4,6 +4,7 @@
import android.content.Context;
import android.content.res.Resources;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.View;
@@ -24,6 +25,8 @@
import com.android.systemui.qs.tileimpl.QSTileViewImplKt;
import com.android.systemui.res.R;
+import org.omnirom.omnilib.utils.OmniUtils;
+
import java.util.ArrayList;
public class TileLayout extends ViewGroup implements QSTileLayout {
@@ -51,7 +54,6 @@
private final boolean mLessRows;
private int mMinRows = 1;
private int mMaxColumns = NO_MAX_COLUMNS;
- protected int mResourceColumns;
private float mSquishinessFraction = 1f;
protected int mLastTileBottom;
protected TextView mTempTextView;
@@ -148,10 +150,6 @@
public boolean updateResources() {
Resources res = getResources();
- int columns = useSmallLandscapeLockscreenResources()
- ? res.getInteger(R.integer.small_land_lockscreen_quick_settings_num_columns)
- : res.getInteger(R.integer.quick_settings_num_columns);
- mResourceColumns = Math.max(1, columns);
mResourceCellHeight = res.getDimensionPixelSize(mResourceCellHeightResId);
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
mSidePadding = useSidePadding() ? mCellMarginHorizontal / 2 : 0;
@@ -190,7 +188,7 @@
private boolean updateColumns() {
int oldColumns = mColumns;
- mColumns = Math.min(mResourceColumns, mMaxColumns);
+ mColumns = Math.min(getResourceColumns(), mMaxColumns);
return oldColumns != mColumns;
}
@@ -270,6 +268,9 @@
}
protected int getCellHeight() {
+ if (OmniUtils.getQSTileLabelHide(mContext)) {
+ return getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
+ }
// Compare estimated height with resource height and return the larger one.
// If estimated height > resource height, it means the resource height is not enough
// for the tile content under current font scaling. Therefore, we need to use the estimated
@@ -377,4 +378,15 @@
info.setCollectionInfo(
new AccessibilityNodeInfo.CollectionInfo(mRecords.size(), 1, false));
}
+
+ public int getResourceColumns() {
+ int resourceColumns = Math.max(2, getResources().getInteger(R.integer.quick_settings_num_columns));
+ return OmniUtils.getQSColumnsCount(mContext, resourceColumns);
+ }
+
+ @Override
+ public void updateSettings() {
+ setMaxColumns(getResourceColumns());
+ requestLayout();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index c606ce4..e270ce0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -34,7 +34,9 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.Dependency;
import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.plugins.qs.QSTile;
@@ -50,6 +52,8 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.util.ArrayList;
import java.util.List;
@@ -57,7 +61,8 @@
/** {@link ViewController} for {@link QSCustomizer}. */
@QSScope
-public class QSCustomizerController extends ViewController<QSCustomizer> {
+public class QSCustomizerController extends ViewController<QSCustomizer>
+ implements OmniSettingsService.OmniSettingsObserver {
private final TileQueryHelper mTileQueryHelper;
private final QSHost mQsHost;
private final TileAdapter mTileAdapter;
@@ -95,12 +100,7 @@
public void onConfigChanged(Configuration newConfig) {
mView.updateNavBackDrop(newConfig, mLightBarController);
mView.updateResources();
- if (mTileAdapter.updateNumColumns()) {
- RecyclerView.LayoutManager lm = mView.getRecyclerView().getLayoutManager();
- if (lm instanceof GridLayoutManager) {
- ((GridLayoutManager) lm).setSpanCount(mTileAdapter.getNumColumns());
- }
- }
+ updateColumns();
}
};
@@ -171,6 +171,11 @@
mToolbar.setOnMenuItemClickListener(mOnMenuItemClickListener);
mToolbar.setNavigationOnClickListener(v -> hide());
+
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_LAYOUT_COLUMNS);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this,
+ OmniSettings.OMNI_QS_LAYOUT_COLUMNS_LANDSCAPE);
}
@Override
@@ -178,6 +183,7 @@
mTileQueryHelper.setListener(null);
mToolbar.setOnMenuItemClickListener(null);
mConfigurationController.removeCallback(mConfigurationListener);
+ Dependency.get(OmniSettingsService.class).removeObserver(this);
}
@@ -281,4 +287,18 @@
}
mTileAdapter.setTileSpecs(specs);
}
+
+ private void updateColumns() {
+ if (mTileAdapter.updateNumColumns()) {
+ RecyclerView.LayoutManager lm = mView.getRecyclerView().getLayoutManager();
+ if (lm instanceof GridLayoutManager) {
+ ((GridLayoutManager) lm).setSpanCount(mTileAdapter.getNumColumns());
+ }
+ }
+ }
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ updateColumns();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index db778a2..4ab3592 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -26,9 +26,11 @@
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
+import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -61,6 +63,8 @@
import com.android.systemui.qs.tileimpl.QSTileViewImpl;
import com.android.systemui.res.R;
+import org.omnirom.omnilib.utils.OmniUtils;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -143,6 +147,7 @@
? context.getResources().getInteger(
R.integer.small_land_lockscreen_quick_settings_num_columns)
: context.getResources().getInteger(NUM_COLUMNS_ID);
+ mNumColumns = OmniUtils.getQSColumnsCount(mContext, mNumColumns);
mAccessibilityDelegate = new TileAdapterDelegate();
mSizeLookup.setSpanIndexCacheEnabled(true);
mTempTextView = new TextView(context);
@@ -169,6 +174,7 @@
? mContext.getResources().getInteger(
R.integer.small_land_lockscreen_quick_settings_num_columns)
: mContext.getResources().getInteger(NUM_COLUMNS_ID);
+ numColumns = OmniUtils.getQSColumnsCount(mContext, numColumns);
if (numColumns != mNumColumns) {
mNumColumns = numColumns;
return true;
@@ -382,7 +388,7 @@
final String titleText;
Resources res = mContext.getResources();
if (mCurrentDrag == null) {
- titleText = res.getString(R.string.drag_to_add_tiles);
+ titleText = res.getString(R.string.drag_or_tap_to_add_tiles);
} else if (!canRemoveTiles() && mCurrentDrag.getAdapterPosition() < mEditIndex) {
titleText = res.getString(R.string.drag_to_remove_disabled, mMinNumTiles);
} else {
@@ -468,6 +474,18 @@
if (position == mFocusIndex) {
focusOnHolder(holder);
}
+ holder.mTileView.setOnTouchListener(new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_UP) {
+ int position = holder.getLayoutPosition();
+ if (position >= mEditIndex || canRemoveTiles()) {
+ move(position, mEditIndex, true);
+ }
+ }
+ return false;
+ }
+ });
}
private void focusOnHolder(Holder holder) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 15e3499..0fb3e7c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -28,6 +28,7 @@
import android.service.quicksettings.TileService;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Log;
import android.widget.Button;
import androidx.annotation.Nullable;
@@ -49,6 +50,8 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -101,19 +104,14 @@
String stock = mContext.getString(R.string.quick_settings_tiles_stock);
String current = Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.QS_TILES);
- final ArrayList<String> possibleTiles = new ArrayList<>();
+ String possible = stock
+ + "," + mContext.getString(R.string.quick_settings_tiles_extra);
+
+ final Set<String> possibleTiles = new HashSet<>();
if (current != null) {
- // The setting QS_TILES is not populated immediately upon Factory Reset
possibleTiles.addAll(Arrays.asList(current.split(",")));
- } else {
- current = "";
}
- String[] stockSplit = stock.split(",");
- for (String spec : stockSplit) {
- if (!current.contains(spec)) {
- possibleTiles.add(spec);
- }
- }
+ possibleTiles.addAll(Arrays.asList(possible.split(",")));
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
possibleTiles.remove("cell");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index b7ebce2..348684a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -33,6 +33,8 @@
import android.graphics.drawable.LayerDrawable
import android.graphics.drawable.RippleDrawable
import android.os.Trace
+import android.os.UserHandle
+import android.provider.Settings
import android.service.quicksettings.Tile
import android.text.TextUtils
import android.util.Log
@@ -73,6 +75,8 @@
import com.android.systemui.res.R
import java.util.Objects
+import org.omnirom.omnilib.utils.OmniUtils
+
private const val TAG = "QSTileViewImpl"
open class QSTileViewImpl
@@ -193,6 +197,9 @@
private var lastDisabledByPolicy = false
private val locInScreen = IntArray(2)
+ private var vertical = false
+ private val forceHideCheveron = true
+ private var labelHide = false
/** Visuo-haptic long-press effects */
private var longPressEffectAnimator: ValueAnimator? = null
@@ -218,8 +225,22 @@
)
}
setId(generateViewId())
- orientation = LinearLayout.HORIZONTAL
- gravity = Gravity.CENTER_VERTICAL or Gravity.START
+
+ vertical = resources.getBoolean(R.bool.qs_tile_vertical_layout)
+ vertical = OmniUtils.getQSTileVerticalLayout(context, if (vertical) 1 else 0)
+ if (vertical) {
+ orientation = LinearLayout.VERTICAL
+ gravity = Gravity.CENTER_HORIZONTAL
+ } else {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.CENTER_VERTICAL or Gravity.START
+ }
+
+ labelHide = OmniUtils.getQSTileLabelHide(context)
+
+ if (labelHide)
+ gravity = Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL
+
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES
clipChildren = false
clipToPadding = false
@@ -228,7 +249,7 @@
setColor(getBackgroundColorForState(QSTile.State.DEFAULT_STATE))
val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
- val startPadding = resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
+ val startPadding = if (vertical) padding else resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
setPaddingRelative(startPadding, padding, padding, padding)
val iconSize = resources.getDimensionPixelSize(R.dimen.qs_icon_size)
@@ -268,11 +289,24 @@
width = iconSize
}
+ vertical = resources.getBoolean(R.bool.qs_tile_vertical_layout)
+ vertical = OmniUtils.getQSTileVerticalLayout(context, if (vertical) 1 else 0)
+ if (vertical) {
+ orientation = LinearLayout.VERTICAL
+ gravity = Gravity.CENTER_HORIZONTAL
+ } else {
+ orientation = LinearLayout.HORIZONTAL
+ gravity = Gravity.CENTER_VERTICAL or Gravity.START
+ }
+
+ if (labelHide)
+ gravity = Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL
+
val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
- val startPadding = resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
+ val startPadding = if (vertical) padding else resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
setPaddingRelative(startPadding, padding, padding, padding)
- val labelMargin = resources.getDimensionPixelSize(R.dimen.qs_label_container_margin)
+ val labelMargin = if (vertical) 0 else resources.getDimensionPixelSize(R.dimen.qs_label_container_margin)
(labelContainer.layoutParams as MarginLayoutParams).apply { marginStart = labelMargin }
(sideView.layoutParams as MarginLayoutParams).apply { marginStart = labelMargin }
@@ -294,7 +328,8 @@
private fun createAndAddLabels() {
labelContainer =
- LayoutInflater.from(context).inflate(R.layout.qs_tile_label, this, false)
+ LayoutInflater.from(context).inflate(if (vertical)
+ R.layout.qs_tile_label_vertical else R.layout.qs_tile_label,this, false)
as IgnorableChildLinearLayout
label = labelContainer.requireViewById(R.id.tile_label)
secondaryLabel = labelContainer.requireViewById(R.id.app_label)
@@ -317,7 +352,8 @@
secondaryLabel.apply { typeface = Typeface.create("gsf-label-medium", Typeface.NORMAL) }
}
- addView(labelContainer)
+ if (!labelHide)
+ addView(labelContainer)
}
private fun createAndAddSideView() {
@@ -836,7 +872,7 @@
customDrawableView.setImageDrawable(state.sideViewCustomDrawable)
customDrawableView.visibility = VISIBLE
chevronView.visibility = GONE
- } else if (state !is AdapterState || state.forceExpandIcon) {
+ } else if ((state !is AdapterState || state.forceExpandIcon) && !forceHideCheveron) {
customDrawableView.setImageDrawable(null)
customDrawableView.visibility = GONE
chevronView.visibility = VISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AODTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AODTile.java
new file mode 100644
index 0000000..66f1c01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AODTile.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 The OmniROM 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.qs.tiles;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.service.quicksettings.Tile;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.animation.Expandable;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.UserSettingObserver;
+import com.android.systemui.res.R;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.util.settings.SecureSettings;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import javax.inject.Inject;
+
+public class AODTile extends QSTileImpl<BooleanState> implements
+ BatteryController.BatteryStateChangeCallback {
+
+ public static final String TILE_SPEC = "aod";
+
+ private boolean mListening;
+ private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_aod);
+ private final BatteryController mBatteryController;
+ private final UserSettingObserver mSetting;
+
+ @Inject
+ public AODTile(
+ QSHost host,
+ QsEventLogger uiEventLogger,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ FalsingManager falsingManager,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ SecureSettings secureSettings,
+ BatteryController batteryController,
+ UserTracker userTracker
+ ) {
+ super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+ statusBarStateController, activityStarter, qsLogger);
+
+ mSetting = new UserSettingObserver(secureSettings, mHandler, Settings.Secure.DOZE_ALWAYS_ON,
+ userTracker.getUserId()) {
+ @Override
+ protected void handleValueChanged(int value, boolean observedChange) {
+ handleRefreshState(value);
+ }
+ };
+
+ mBatteryController = batteryController;
+ batteryController.observe(getLifecycle(), this);
+ }
+
+ @Override
+ public void onPowerSaveChanged(boolean isPowerSave) {
+ refreshState();
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ mSetting.setListening(false);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_dozeAlwaysOnDisplayAvailable);
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ BooleanState state = new BooleanState();
+ state.handlesLongClick = false;
+ return state;
+ }
+
+ @Override
+ public void handleSetListening(boolean listening) {
+ super.handleSetListening(listening);
+ mSetting.setListening(listening);
+ }
+
+ @Override
+ protected void handleUserSwitch(int newUserId) {
+ mSetting.setUserId(newUserId);
+ handleRefreshState(mSetting.getValue());
+ }
+
+ @Override
+ public void handleClick(@Nullable Expandable expandable) {
+ mSetting.setValue(mState.value ? 0 : 1);
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_aod_label);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue();
+ final boolean enable = value != 0;
+ state.icon = mIcon;
+ state.value = enable;
+ state.label = mContext.getString(R.string.quick_settings_aod_label);
+ if (mBatteryController.isAodPowerSave()) {
+ state.state = Tile.STATE_UNAVAILABLE;
+ state.secondaryLabel = mContext.getString(
+ R.string.quick_settings_aod_off_powersave_label);
+ } else {
+ state.state = enable ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ if (enable) {
+ state.secondaryLabel = mContext.getString(R.string.aod_on);
+ } else {
+ state.secondaryLabel = mContext.getString(R.string.aod_off);
+ }
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.CUSTOM_QUICK_TILES;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
index 9efdd98..ae79d8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
@@ -2,10 +2,12 @@
import android.app.AlarmManager
import android.app.AlarmManager.AlarmClockInfo
+import android.app.NotificationManager
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.provider.AlarmClock
+import android.provider.Settings
import android.service.quicksettings.Tile
import android.text.TextUtils
import android.text.format.DateFormat
@@ -27,6 +29,7 @@
import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.NextAlarmController
+import com.android.systemui.statusbar.policy.ZenModeController
import java.util.Locale
import javax.inject.Inject
@@ -44,6 +47,7 @@
qsLogger: QSLogger,
private val userTracker: UserTracker,
nextAlarmController: NextAlarmController,
+ private val zenModeController: ZenModeController,
) :
QSTileImpl<QSTile.State>(
host,
@@ -59,6 +63,7 @@
private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null
private var icon: QSTile.Icon? = null
+ private val iconDim = ResourceIcon.get(R.drawable.ic_alarm_dim)
@VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
private val callback =
NextAlarmController.NextAlarmChangeCallback { nextAlarm ->
@@ -66,8 +71,14 @@
refreshState()
}
+ private val zenCallback = object : ZenModeController.Callback {
+ override fun onZenChanged(zen: Int) { refreshState() }
+ override fun onConsolidatedPolicyChanged(policy: NotificationManager.Policy) { refreshState() }
+ }
+
init {
nextAlarmController.observe(this, callback)
+ zenModeController.observe(this, zenCallback)
}
override fun newTileState(): QSTile.State {
@@ -98,8 +109,8 @@
if (icon == null) {
icon = maybeLoadResourceIcon(R.drawable.ic_alarm)
}
- state.icon = icon
- state.label = tileLabel
+ state.icon = if (zenAllowsAlarm()) icon else iconDim
+ state.label = if (zenAllowsAlarm()) tileLabel else tileLabel.toString() + mContext.getString(R.string.alarm_title_dnd_indicator)
lastAlarmInfo?.let {
state.secondaryLabel = formatNextAlarm(it)
state.state = Tile.STATE_ACTIVE
@@ -133,6 +144,21 @@
return null
}
+
+ private fun zenAllowsAlarm() : Boolean {
+ val zen = zenModeController.getZen()
+ if (zen == Settings.Global.ZEN_MODE_OFF) {
+ return true
+ }
+ if (zen == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ return false
+ }
+ if (zen == Settings.Global.ZEN_MODE_ALARMS) {
+ return true
+ }
+ return (zenModeController.getConsolidatedPolicy().priorityCategories and NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) != 0
+ }
+
companion object {
const val TILE_SPEC = "alarm"
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java
new file mode 100644
index 0000000..43660c0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ * Copyright (c) 2017 The LineageOS 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.qs.tiles;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.service.quicksettings.Tile;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.animation.Expandable;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import javax.inject.Inject;
+
+/** Quick settings tile: Caffeine **/
+public class CaffeineTile extends QSTileImpl<BooleanState> {
+ public static final String TILE_SPEC = "caffeine";
+
+ private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_caffeine);
+
+ private final PowerManager.WakeLock mWakeLock;
+ private int mSecondsRemaining;
+ private int mDuration;
+ private static int[] DURATIONS = new int[] {
+ 5 * 60, // 5 min
+ 10 * 60, // 10 min
+ 30 * 60, // 30 min
+ -1, // infinity
+ };
+ private static final int INFINITE_DURATION_INDEX = DURATIONS.length - 1;
+ private CountDownTimer mCountdownTimer = null;
+ public long mLastClickTime = -1;
+ private final Receiver mReceiver = new Receiver();
+
+ @Inject
+ public CaffeineTile(
+ QSHost host,
+ QsEventLogger uiEventLogger,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ FalsingManager falsingManager,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger
+ ) {
+ super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+ statusBarStateController, activityStarter, qsLogger);
+ mWakeLock = mContext.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.FULL_WAKE_LOCK, "CaffeineTile");
+ mReceiver.init();
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ stopCountDown();
+ mReceiver.destroy();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+
+ @Override
+ public void handleSetListening(boolean listening) {
+ }
+
+ @Override
+ protected void handleClick(@Nullable Expandable expandable) {
+ // If last user clicks < 5 seconds
+ // we cycle different duration
+ // otherwise toggle on/off
+ if (mWakeLock.isHeld() && (mLastClickTime != -1) &&
+ (SystemClock.elapsedRealtime() - mLastClickTime < 5000)) {
+ // cycle duration
+ mDuration++;
+ if (mDuration >= DURATIONS.length) {
+ // all durations cycled, turn if off
+ mDuration = -1;
+ stopCountDown();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ } else {
+ // change duration
+ startCountDown(DURATIONS[mDuration]);
+ if (!mWakeLock.isHeld()) {
+ mWakeLock.acquire();
+ }
+ }
+ } else {
+ // toggle
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ stopCountDown();
+ } else {
+ mWakeLock.acquire();
+ mDuration = 0;
+ startCountDown(DURATIONS[mDuration]);
+ }
+ }
+ mLastClickTime = SystemClock.elapsedRealtime();
+ refreshState();
+ }
+
+ @Override
+ protected void handleLongClick(@Nullable Expandable expandable) {
+ if (mWakeLock.isHeld()) {
+ if (mDuration == INFINITE_DURATION_INDEX) {
+ return;
+ }
+ } else {
+ mWakeLock.acquire();
+ }
+ mDuration = INFINITE_DURATION_INDEX;
+ startCountDown(DURATIONS[INFINITE_DURATION_INDEX]);
+ refreshState();
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_caffeine_label);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.CUSTOM_QUICK_TILES;
+ }
+
+ private void startCountDown(long duration) {
+ stopCountDown();
+ mSecondsRemaining = (int)duration;
+ if (duration == -1) {
+ // infinity timing, no need to start timer
+ return;
+ }
+ mCountdownTimer = new CountDownTimer(duration * 1000, 1000) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ mSecondsRemaining = (int) (millisUntilFinished / 1000);
+ refreshState();
+ }
+
+ @Override
+ public void onFinish() {
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ refreshState();
+ }
+
+ }.start();
+ }
+
+ private void stopCountDown() {
+ if (mCountdownTimer != null) {
+ mCountdownTimer.cancel();
+ mCountdownTimer = null;
+ }
+ }
+
+ private String formatValueWithRemainingTime() {
+ if (mSecondsRemaining == -1) {
+ return "\u221E"; // infinity
+ }
+ return String.format("%02d:%02d",
+ mSecondsRemaining / 60 % 60, mSecondsRemaining % 60);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.value = mWakeLock.isHeld();
+ state.icon = mIcon;
+ state.label = mContext.getString(R.string.quick_settings_caffeine_label);
+ if (state.value) {
+ state.secondaryLabel = formatValueWithRemainingTime();
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_caffeine_on);
+ state.state = Tile.STATE_ACTIVE;
+ } else {
+ state.secondaryLabel = null;
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_quick_settings_caffeine_off);
+ state.state = Tile.STATE_INACTIVE;
+ }
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ public void init() {
+ // Register for Intent broadcasts for...
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ mContext.registerReceiver(this, filter, null, mHandler);
+ }
+
+ public void destroy() {
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ // disable caffeine if user force off (power button)
+ stopCountDown();
+ if (mWakeLock.isHeld())
+ mWakeLock.release();
+ refreshState();
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 30c2adf..56916b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -90,7 +90,7 @@
private final TileJavaAdapter mJavaAdapter;
private final FeatureFlags mFeatureFlags;
private boolean mCastTransportAllowed;
- private boolean mHotspotConnected;
+ private boolean mHotspotEnabled;
@Inject
public CastTile(
@@ -320,23 +320,23 @@
}
private boolean canCastToNetwork() {
- return mCastTransportAllowed || mHotspotConnected;
+ return mCastTransportAllowed || mHotspotEnabled;
}
- private void setCastTransportAllowed(boolean connected) {
- if (connected != mCastTransportAllowed) {
- mCastTransportAllowed = connected;
- // Hotspot is not connected, so changes here should update
- if (!mHotspotConnected) {
+ private void setCastTransportAllowed(boolean enabled) {
+ if (enabled != mCastTransportAllowed) {
+ mCastTransportAllowed = enabled;
+ // Hotspot is not enabled, so changes here should update
+ if (!mHotspotEnabled) {
refreshState();
}
}
}
- private void setHotspotConnected(boolean connected) {
- if (connected != mHotspotConnected) {
- mHotspotConnected = connected;
- // Wifi is not connected, so changes here should update
+ private void setHotspotEnabled(boolean enabled) {
+ if (enabled != mHotspotEnabled) {
+ mHotspotEnabled = enabled;
+ // Wifi is not enabled, so changes here should update
if (!mCastTransportAllowed) {
refreshState();
}
@@ -353,10 +353,7 @@
private final SignalCallback mSignalCallback = new SignalCallback() {
@Override
public void setWifiIndicators(@NonNull WifiIndicators indicators) {
- // statusIcon.visible has the connected status information
- boolean enabledAndConnected = indicators.enabled
- && (indicators.qsIcon != null && indicators.qsIcon.visible);
- setCastTransportAllowed(enabledAndConnected);
+ setCastTransportAllowed(indicators.enabled);
}
};
@@ -364,8 +361,7 @@
new HotspotController.Callback() {
@Override
public void onHotspotChanged(boolean enabled, int numDevices) {
- boolean enabledAndConnected = enabled && numDevices > 0;
- setHotspotConnected(enabledAndConnected);
+ setHotspotEnabled(enabled);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSwitchTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSwitchTile.java
new file mode 100644
index 0000000..a672aa5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSwitchTile.java
@@ -0,0 +1,239 @@
+package com.android.systemui.qs.tiles;
+
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.systemui.animation.Expandable;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon;
+import com.android.systemui.res.R;
+
+import java.util.concurrent.Executors;
+import java.util.List;
+
+import javax.inject.Inject;
+
+public class DataSwitchTile extends QSTileImpl<BooleanState> {
+ public static final String TILE_SPEC = "dataswitch";
+
+ private boolean mCanSwitch = true;
+ private boolean mRegistered;
+ private int mSimCount;
+
+ private final Intent mLongClickIntent;
+ private final String mTileLabel;
+ private final BroadcastReceiver mSimReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "mSimReceiver:onReceive");
+ refreshState();
+ }
+ };
+ private final PhoneStateListener mPhoneStateListener;
+ private final SubscriptionManager mSubscriptionManager;
+ private final TelephonyManager mTelephonyManager;
+
+ @Inject
+ public DataSwitchTile(
+ QSHost host,
+ QsEventLogger uiEventLogger,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ FalsingManager falsingManager,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger
+ ) {
+ super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+ statusBarStateController, activityStarter, qsLogger);
+ mLongClickIntent = new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
+ mTileLabel = mContext.getString(R.string.qs_data_switch_label);
+ mSubscriptionManager = SubscriptionManager.from(mContext);
+ mTelephonyManager = TelephonyManager.from(mContext);
+ mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String arg1) {
+ mCanSwitch = mTelephonyManager.getCallState() == 0;
+ refreshState();
+ }
+ };
+ }
+
+ @Override
+ public boolean isAvailable() {
+ int count = TelephonyManager.getDefault().getPhoneCount();
+ if (DEBUG) Log.d(TAG, "phoneCount: " + count);
+ return count >= 2;
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ final BooleanState state = new BooleanState();
+ state.label = mContext.getString(R.string.qs_data_switch_label);
+ return state;
+ }
+
+ @Override
+ public void handleSetListening(boolean listening) {
+ if (listening) {
+ if (!mRegistered) {
+ final IntentFilter filter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ mContext.registerReceiver(mSimReceiver, filter);
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ mRegistered = true;
+ }
+ refreshState();
+ } else if (mRegistered) {
+ mContext.unregisterReceiver(mSimReceiver);
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ mRegistered = false;
+ }
+ }
+
+ private void updateSimCount() {
+ String simState = SystemProperties.get("gsm.sim.state");
+ if (DEBUG) Log.d(TAG, "DataSwitchTile:updateSimCount:simState=" + simState);
+ mSimCount = 0;
+ try {
+ final String[] sims = TextUtils.split(simState, ",");
+ for (String sim : sims) {
+ if (!sim.isEmpty()
+ && !sim.equalsIgnoreCase(IccCardConstants.INTENT_VALUE_ICC_ABSENT)
+ && !sim.equalsIgnoreCase(IccCardConstants.INTENT_VALUE_ICC_NOT_READY)) {
+ mSimCount++;
+ }
+ }
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Error on parsing sim state " + e.getMessage());
+ }
+ if (DEBUG) Log.d(TAG, "DataSwitchTile:updateSimCount:mSimCount=" + mSimCount);
+ }
+
+ @Override
+ protected void handleClick(@Nullable Expandable expandable) {
+ if (!mCanSwitch) {
+ if (DEBUG) Log.d(TAG, "Call state=" + mTelephonyManager.getCallState());
+ } else if (mSimCount == 0) {
+ if (DEBUG) Log.d(TAG, "handleClick:no sim card");
+ } else if (mSimCount == 1) {
+ if (DEBUG) Log.d(TAG, "handleClick:only one sim card");
+ } else {
+ Executors.newSingleThreadExecutor().execute(() -> {
+ toggleMobileDataEnabled();
+ refreshState();
+ });
+ }
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return mLongClickIntent;
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mTileLabel;
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ boolean activeSIMZero;
+ if (arg == null) {
+ int defaultPhoneId = mSubscriptionManager.getPhoneId(mSubscriptionManager.getDefaultDataSubscriptionId());
+ if (DEBUG) Log.d(TAG, "default data phone id=" + defaultPhoneId);
+ activeSIMZero = defaultPhoneId == 0;
+ } else {
+ activeSIMZero = (Boolean) arg;
+ }
+ updateSimCount();
+ state.value = mSimCount == 2;
+ if (mSimCount == 1 || mSimCount == 2) {
+ state.icon = ResourceIcon.get(activeSIMZero
+ ? R.drawable.ic_qs_data_switch_1
+ : R.drawable.ic_qs_data_switch_2);
+ state.secondaryLabel = mContext.getString(activeSIMZero
+ ? R.string.qs_data_sim_1
+ : R.string.qs_data_sim_2);
+ } else {
+ if (mSimCount == 0) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_data_switch_0);
+ state.secondaryLabel = mContext.getString(R.string.qs_data_no_sim);
+ } else {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_data_switch_1);
+ state.secondaryLabel = mContext.getString(R.string.qs_data_sim_1);
+ }
+ }
+ if (mSimCount < 2 || !mCanSwitch) {
+ state.state = 0;
+ if (!mCanSwitch && DEBUG) Log.d(TAG, "call state isn't idle, set to unavailable.");
+ } else {
+ state.state = state.value ? 2 : 1;
+ }
+
+ state.contentDescription =
+ mContext.getString(activeSIMZero
+ ? R.string.qs_data_switch_changed_1
+ : R.string.qs_data_switch_changed_2);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.CUSTOM_QUICK_TILES;
+ }
+
+ /**
+ * Set whether to enable data for {@code subId}, also whether to disable data for other
+ * subscription
+ */
+ private void toggleMobileDataEnabled() {
+ // Get opposite slot 2 ^ 3 = 1, 1 ^ 3 = 2
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId() ^ 3;
+ final TelephonyManager telephonyManager =
+ mTelephonyManager.createForSubscriptionId(subId);
+ telephonyManager.setDataEnabled(true);
+ mSubscriptionManager.setDefaultDataSubId(subId);
+ if (DEBUG) Log.d(TAG, "Enabled subID: " + subId);
+
+ final List<SubscriptionInfo> subInfoList =
+ mSubscriptionManager.getActiveSubscriptionInfoList(true);
+ if (subInfoList != null) {
+ // We never disable mobile data for opportunistic subscriptions.
+ subInfoList.stream()
+ .filter(subInfo -> !subInfo.isOpportunistic())
+ .map(subInfo -> subInfo.getSubscriptionId())
+ .filter(id -> id != subId)
+ .forEach(id -> {
+ mTelephonyManager.createForSubscriptionId(id).setDataEnabled(false);
+ if (DEBUG) Log.d(TAG, "Disabled subID: " + id);
+ });
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 683e4e9..06992b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -102,9 +102,10 @@
@Override
public boolean isAvailable() {
String stockTiles = mContext.getString(R.string.quick_settings_tiles_stock);
+ String extraStockTiles = mContext.getString(R.string.quick_settings_tiles_extra);
// For the restore from backup case
// Return false when "nfc" is not listed in quick_settings_tiles_stock.
- if (stockTiles.contains(NFC)) {
+ if (stockTiles.contains(NFC) || extraStockTiles.contains(NFC)) {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC);
}
return false;
@@ -160,7 +161,7 @@
private NfcAdapter getAdapter() {
if (mAdapter == null) {
try {
- mAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ mAdapter = NfcAdapter.getDefaultAdapter(mContext.getApplicationContext());
} catch (UnsupportedOperationException e) {
mAdapter = null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenshotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenshotTile.java
new file mode 100644
index 0000000..a008d12
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenshotTile.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The OmniROM 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.qs.tiles;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.quicksettings.Tile;
+import android.view.WindowManager;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
+import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.util.ScreenshotHelper;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.animation.Expandable;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.internal.R;
+
+import javax.inject.Inject;
+
+/** Quick settings tile: Screenshot **/
+public class ScreenshotTile extends QSTileImpl<BooleanState> {
+ public static final String TILE_SPEC = "screenshot";
+ private final PanelInteractor mPanelInteractor;
+
+ @Inject
+ public ScreenshotTile(
+ QSHost host,
+ QsEventLogger uiEventLogger,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ FalsingManager falsingManager,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ PanelInteractor panelInteractor
+ ) {
+ super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+ statusBarStateController, activityStarter, qsLogger);
+ mPanelInteractor = panelInteractor;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.CUSTOM_QUICK_TILES;
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ public void handleSetListening(boolean listening) {}
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void handleClick(@Nullable Expandable expandable) {
+ mPanelInteractor.collapsePanels();
+ final ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
+ mHandler.postDelayed(() -> {
+ screenshotHelper.takeScreenshot(SCREENSHOT_GLOBAL_ACTIONS, mHandler, null);
+ }, 1000);
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.global_action_screenshot);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ state.label = mContext.getString(
+ R.string.global_action_screenshot);
+ state.contentDescription = mContext.getString(
+ R.string.global_action_screenshot);
+ state.icon = ResourceIcon.get(R.drawable.ic_screenshot);
+ state.value = true;
+ state.state = Tile.STATE_INACTIVE;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index f7b5271..48657ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
+import android.media.AudioAttributes;
import android.media.MediaRecorder;
import android.media.projection.StopReason;
import android.net.Uri;
@@ -182,6 +183,8 @@
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
+ channel.setSound(null, // silent
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
mNotificationManager.createNotificationChannel(channel);
int currentUid = Process.myUid();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 15638d3..a409fc6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -16,6 +16,7 @@
package com.android.systemui.screenshot
+import android.app.PendingIntent
import android.content.ClipData
import android.content.ClipDescription
import android.content.ComponentName
@@ -91,6 +92,16 @@
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
+ fun createDelete(rawUri: Uri, context: Context): PendingIntent {
+ return PendingIntent.getBroadcast(context, rawUri.toString().hashCode(),
+ Intent(context, DeleteScreenshotReceiver::class.java)
+ .putExtra(SmartActionsReceiver.SCREENSHOT_URI_ID, rawUri.toString())
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ (PendingIntent.FLAG_CANCEL_CURRENT
+ or PendingIntent.FLAG_ONE_SHOT
+ or PendingIntent.FLAG_IMMUTABLE))
+ }
+
/** @return an Intent to start the LongScreenshotActivity */
fun createLongScreenshotIntent(owner: UserHandle, context: Context): Intent {
return Intent(context, LongScreenshotActivity::class.java)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java
new file mode 100644
index 0000000..e556e4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/DeleteScreenshotReceiver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 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.screenshot;
+
+import static com.android.systemui.screenshot.SmartActionsReceiver.ACTION_TYPE_DELETE;
+import static com.android.systemui.screenshot.SmartActionsReceiver.EXTRA_ID;
+import static com.android.systemui.screenshot.SmartActionsReceiver.EXTRA_SMART_ACTIONS_ENABLED;
+import static com.android.systemui.screenshot.SmartActionsReceiver.SCREENSHOT_URI_ID;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.android.systemui.dagger.qualifiers.Background;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * Removes the file at a provided URI.
+ */
+public class DeleteScreenshotReceiver extends BroadcastReceiver {
+
+ private final ScreenshotSmartActions mScreenshotSmartActions;
+ private final Executor mBackgroundExecutor;
+
+ @Inject
+ public DeleteScreenshotReceiver(ScreenshotSmartActions screenshotSmartActions,
+ @Background Executor backgroundExecutor) {
+ mScreenshotSmartActions = screenshotSmartActions;
+ mBackgroundExecutor = backgroundExecutor;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!intent.hasExtra(SCREENSHOT_URI_ID)) {
+ return;
+ }
+
+ // And delete the image from the media store
+ final Uri uri = Uri.parse(intent.getStringExtra(SCREENSHOT_URI_ID));
+ mBackgroundExecutor.execute(() -> {
+ ContentResolver resolver = context.getContentResolver();
+ resolver.delete(uri, null, null);
+ });
+ if (intent.getBooleanExtra(EXTRA_SMART_ACTIONS_ENABLED, false)) {
+ mScreenshotSmartActions.notifyScreenshotAction(
+ intent.getStringExtra(EXTRA_ID), ACTION_TYPE_DELETE, false, null);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
index 1c232e9..05aa887 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionsProvider.kt
@@ -25,9 +25,11 @@
import com.android.systemui.Flags.screenshotContextUrl
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.res.R
+import com.android.systemui.screenshot.ActionIntentCreator.createDelete
import com.android.systemui.screenshot.ActionIntentCreator.createEdit
import com.android.systemui.screenshot.ActionIntentCreator.createShareWithSubject
import com.android.systemui.screenshot.ActionIntentCreator.createShareWithText
+import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DELETE_TAPPED
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_EDIT_TAPPED
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_SHARE_TAPPED
@@ -99,7 +101,7 @@
actionsCallback.provideActionButton(
ActionButtonAppearance(
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_share),
- context.resources.getString(R.string.screenshot_share_label),
+ context.resources.getString(R.string.screenshot_share_label_empty),
context.resources.getString(R.string.screenshot_share_description),
),
showDuringEntrance = true,
@@ -121,7 +123,7 @@
actionsCallback.provideActionButton(
ActionButtonAppearance(
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_edit),
- context.resources.getString(R.string.screenshot_edit_label),
+ context.resources.getString(R.string.screenshot_edit_label_empty),
context.resources.getString(R.string.screenshot_edit_description),
),
showDuringEntrance = true,
@@ -136,6 +138,23 @@
)
}
}
+
+ actionsCallback.provideActionButton(
+ ActionButtonAppearance(
+ AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_delete),
+ context.resources.getString(R.string.screenshot_delete_label_empty),
+ context.resources.getString(R.string.screenshot_delete_description),
+ ),
+ showDuringEntrance = true,
+ ) {
+ debugLog(LogConfig.DEBUG_ACTIONS) { "Delete tapped" }
+ uiEventLogger.log(SCREENSHOT_DELETE_TAPPED, 0, request.packageNameString)
+ onDeferrableActionTapped { result ->
+ actionExecutor.sendPendingIntent(
+ createDelete(result.uri, context)
+ )
+ }
+ }
}
override fun onScrollChipReady(onClick: Runnable) {
@@ -144,7 +163,7 @@
actionsCallback.provideActionButton(
ActionButtonAppearance(
AppCompatResources.getDrawable(context, R.drawable.ic_screenshot_scroll),
- context.resources.getString(R.string.screenshot_scroll_label),
+ context.resources.getString(R.string.screenshot_scroll_label_empty),
context.resources.getString(R.string.screenshot_scroll_label),
),
showDuringEntrance = true,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 7a62bae..ce1acd6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -54,6 +54,8 @@
SCREENSHOT_EDIT_TAPPED(308),
@UiEvent(doc = "screenshot share button tapped")
SCREENSHOT_SHARE_TAPPED(309),
+ @UiEvent(doc = "screenshot delete button tapped")
+ SCREENSHOT_DELETE_TAPPED(369),
@UiEvent(doc = "screenshot smart action chip tapped")
SCREENSHOT_SMART_ACTION_TAPPED(374),
@UiEvent(doc = "screenshot scroll tapped")
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
index f902693..0153022 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
@@ -34,6 +34,7 @@
private static final String TAG = "SmartActionsReceiver";
// These strings are used for communicating the action invoked to
// ScreenshotNotificationSmartActionsProvider.
+ public static final String ACTION_TYPE_DELETE = "Delete";
public static final String EXTRA_ACTION_TYPE = "android:screenshot_action_type";
public static final String EXTRA_ID = "android:screenshot_id";
public static final String EXTRA_SMART_ACTIONS_ENABLED = "android:smart_actions_enabled";
@@ -41,6 +42,7 @@
public static final String EXTRA_ACTION_INTENT_FILLIN =
"android:screenshot_action_intent_fillin";
+ static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
private final ScreenshotSmartActions mScreenshotSmartActions;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 90d27f4..3036961 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -488,6 +488,7 @@
// animating it from two different sources causes janky motion.
// Don't animate if the value is changed via the brightness keys of a keyboard.
mControl.setValue(target);
+ mControl.updateThumb(target);
mControlValueInitialized = true;
}
mSliderAnimator = ValueAnimator.ofInt(mControl.getValue(), target);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index 503d0bf..bf43051 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -247,6 +247,10 @@
return mView.isVisibleToUser();
}
+ public void updateThumb(int value) {
+ mView.updateThumb(value);
+ }
+
private final SeekBar.OnSeekBarChangeListener mSeekListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
@@ -257,6 +261,7 @@
mBrightnessSliderHapticPlugin.onProgressChanged(progress, true);
}
}
+ mView.updateThumb(progress);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index a39d25a..2323728 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -166,6 +166,13 @@
mSlider.setProgress(value);
}
+ public void updateThumb(int value) {
+ if (mSlider.getThumb() != null) {
+ final int level = (int) (((float)value / getMax()) * /*ProgressBar.MAX_LEVEL*/ 10000);
+ mSlider.getThumb().setLevel(level);
+ }
+ }
+
/**
* @return the current value of the {@link ToggleSeekBar}
*/
@@ -213,10 +220,11 @@
private void applySliderScale() {
if (mProgressDrawable != null) {
- final Rect r = mProgressDrawable.getBounds();
+ // TODO
+ /*final Rect r = mProgressDrawable.getBounds();
int height = (int) (mProgressDrawable.getIntrinsicHeight() * mScale);
int inset = (mProgressDrawable.getIntrinsicHeight() - height) / 2;
- mProgressDrawable.setBounds(r.left, inset, r.right, inset + height);
+ mProgressDrawable.setBounds(r.left, inset, r.right, inset + height);*/
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index ed69d35..7ff112a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -40,4 +40,6 @@
void hideView();
void showToast(@StringRes int resId);
boolean isVisible();
+
+ void updateThumb(int value);
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index e8a792c..defcc91 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -344,6 +344,11 @@
v.pivotY = v.height.toFloat() / 2
}
clock.setOnClickListener { launchClockActivity() }
+ batteryIcon.setOnClickListener {
+ activityStarter.postStartActivityDismissingKeyguard(
+ Intent(Intent.ACTION_POWER_USAGE_SUMMARY), 0
+ )
+ }
dumpManager.registerDumpable(this)
configurationController.addCallback(configurationControllerListener)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 862f33bb..a75498d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -183,6 +183,9 @@
private static final int MSG_ENTER_DESKTOP = 80 << MSG_SHIFT;
private static final int MSG_SET_SPLITSCREEN_FOCUS = 81 << MSG_SHIFT;
private static final int MSG_TOGGLE_QUICK_SETTINGS_PANEL = 82 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_CAMERA_FLASH = 83 << MSG_SHIFT;
+ private static final int MSG_TOGGLE_CAMERA_FLASH_STATE = 84 << MSG_SHIFT;
+
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1;
@@ -366,7 +369,7 @@
default void showPinningEnterExitToast(boolean entering) { }
default void showPinningEscapeToast() { }
default void handleShowGlobalActionsMenu() { }
- default void handleShowShutdownUi(boolean isReboot, String reason) { }
+ default void handleShowShutdownUi(boolean isReboot, String reason, boolean rebootCustom) { }
default void showWirelessChargingAnimation(int batteryLevel) { }
@@ -574,6 +577,12 @@
* @see IStatusBar#moveFocusedTaskToDesktop(int)
*/
default void moveFocusedTaskToDesktop(int displayId) {}
+
+ /**
+ * Omni
+ */
+ default void toggleCameraFlash() { }
+ default void toggleCameraFlashState(boolean enable) { }
}
@VisibleForTesting
@@ -1047,10 +1056,10 @@
}
@Override
- public void showShutdownUi(boolean isReboot, String reason) {
+ public void showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI);
- mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, 0, reason)
+ mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, rebootCustom ? 1 : 0, reason)
.sendToTarget();
}
}
@@ -1492,6 +1501,22 @@
mHandler.obtainMessage(MSG_ENTER_DESKTOP, args).sendToTarget();
}
+ @Override
+ public void toggleCameraFlash() {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_TOGGLE_CAMERA_FLASH);
+ mHandler.sendEmptyMessage(MSG_TOGGLE_CAMERA_FLASH);
+ }
+ }
+
+ @Override
+ public void toggleCameraFlashState(boolean enable) {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_TOGGLE_CAMERA_FLASH_STATE);
+ mHandler.obtainMessage(MSG_TOGGLE_CAMERA_FLASH_STATE,enable ? 1 : 0, 0, null).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -1699,7 +1724,7 @@
break;
case MSG_SHOW_SHUTDOWN_UI:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj);
+ mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj, msg.arg2 != 0);
}
break;
case MSG_SET_TOP_APP_HIDES_STATUS_BAR:
@@ -2013,6 +2038,16 @@
}
break;
}
+ case MSG_TOGGLE_CAMERA_FLASH:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleCameraFlash();
+ }
+ break;
+ case MSG_TOGGLE_CAMERA_FLASH_STATE:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleCameraFlashState(msg.arg1 != 0);
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index f37f7f9..0676fe4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -137,6 +137,8 @@
import com.google.errorprone.annotations.CompileTimeConstant;
+import org.omnirom.omnilib.utils.OmniUtils;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.util.ArrayList;
@@ -471,6 +473,7 @@
private final Runnable mReflingAndAnimateScroll = this::animateScroll;
private int mCornerRadius;
private int mMinimumPaddings;
+ private int mQsTileColumns;
private int mQsTilePadding;
private boolean mSkinnyNotifsInLandscape;
private int mSidePaddings;
@@ -986,6 +989,8 @@
mBottomPadding = res.getDimensionPixelSize(R.dimen.notification_panel_padding_bottom);
mMinimumPaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
mQsTilePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal);
+ mQsTileColumns = res.getInteger(R.integer.quick_settings_num_columns);
+ mQsTileColumns = OmniUtils.getQSColumnsCount(mContext, mQsTileColumns);
mSidePaddings = mMinimumPaddings; // Updated in onMeasure by updateSidePadding()
mMinInteractionHeight = res.getDimensionPixelSize(
R.dimen.notification_min_interaction_height);
@@ -1023,7 +1028,7 @@
}
final int innerWidth = viewWidth - mMinimumPaddings * 2;
- final int qsTileWidth = (innerWidth - mQsTilePadding * 3) / 4;
+ final int qsTileWidth = (innerWidth - mQsTilePadding * (mQsTileColumns - 1)) / mQsTileColumns;
mSidePaddings = mMinimumPaddings + qsTileWidth + mQsTilePadding;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index adfcb71..ad939f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -46,6 +46,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.Dependency;
import com.android.systemui.emergency.EmergencyGesture;
import com.android.systemui.emergency.EmergencyGestureModule.EmergencyGestureIntentFactory;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -66,8 +67,9 @@
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
@@ -120,6 +122,9 @@
private final EmergencyGestureIntentFactory mEmergencyGestureIntentFactory;
+ /*omni add-on*/
+ private FlashlightController mFlashlightController;
+
@Inject
CentralSurfacesCommandQueueCallbacks(
CentralSurfaces centralSurfaces,
@@ -186,6 +191,9 @@
mVibratorOptional, resources);
mActivityStarter = activityStarter;
mEmergencyGestureIntentFactory = emergencyGestureIntentFactory;
+
+ // omni
+ mFlashlightController = Dependency.get(FlashlightController.class);
}
@Override
@@ -577,4 +585,24 @@
HapticFeedbackConstants.GESTURE_START
);
}
+
+ @Override
+ public void toggleCameraFlash() {
+ if (mFlashlightController != null) {
+ mFlashlightController.initFlashLight();
+ if (mFlashlightController.hasFlashlight() && mFlashlightController.isAvailable()) {
+ mFlashlightController.setFlashlight(!mFlashlightController.isEnabled());
+ }
+ }
+ }
+
+ @Override
+ public void toggleCameraFlashState(boolean enable) {
+ if (mFlashlightController != null) {
+ mFlashlightController.initFlashLight();
+ if (mFlashlightController.hasFlashlight() && mFlashlightController.isAvailable()) {
+ mFlashlightController.setFlashlight(enable);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 7bea480..d6835d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -241,6 +241,8 @@
import dagger.Lazy;
+import org.omnirom.omnilib.utils.OmniUtils;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
@@ -347,6 +349,16 @@
return mQSPanelController;
}
+ /** */
+ public void toggleCameraFlash() {
+ mCommandQueueCallbacks.toggleCameraFlash();
+ }
+
+ /** */
+ public void toggleCameraFlashState(boolean enable) {
+ mCommandQueueCallbacks.toggleCameraFlashState(enable);
+ }
+
/**
* The {@link StatusBarState} of the status bar.
*/
@@ -1465,6 +1477,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(OmniUtils.ACTION_DISMISS_KEYGUARD);
mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
}
@@ -1962,6 +1975,15 @@
}
finishBarAnimations();
mNotificationsController.resetUserExpandedStates();
+ } else if (OmniUtils.ACTION_DISMISS_KEYGUARD.equals(action)) {
+ if (intent.hasExtra(OmniUtils.DISMISS_KEYGUARD_EXTRA_INTENT)) {
+ Intent launchIntent = (Intent) intent.getParcelableExtra(OmniUtils.DISMISS_KEYGUARD_EXTRA_INTENT);
+ mActivityStarter.startActivityDismissingKeyguard(
+ launchIntent,
+ true /* onlyProvisioned */,
+ true /* dismissShade */,
+ null /* customMessage */);
+ }
}
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 4915b84..8f1d113 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -93,7 +93,6 @@
private final UserTracker mUserTracker;
private final SecureSettings mSecureSettings;
- private boolean mDozeAlwaysOn;
private boolean mControlScreenOffAnimation;
private boolean mIsQuickPickupEnabled;
@@ -158,7 +157,6 @@
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
tunerService.addTunable(
this,
- Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
configurationController.addCallback(this);
statusBarStateController.addCallback(this);
@@ -275,7 +273,8 @@
* @return {@code true} if enabled and available.
*/
public boolean getAlwaysOn() {
- return mDozeAlwaysOn && !mBatteryController.isAodPowerSave();
+ return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT)
+ && !mBatteryController.isAodPowerSave();
}
/**
@@ -422,12 +421,6 @@
@Override
public void onTuningChanged(String key, String newValue) {
- mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(mUserTracker.getUserId());
-
- if (key.equals(Settings.Secure.DOZE_ALWAYS_ON)) {
- updateControlScreenOff();
- }
-
dispatchAlwaysOnEvent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index f8eae36..10b6711 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -24,18 +24,30 @@
import android.app.AlarmManager.AlarmClockInfo;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Global;
+import android.provider.Settings.System;
import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
import android.text.format.DateFormat;
@@ -45,12 +57,16 @@
import androidx.lifecycle.Observer;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
+import com.android.systemui.Dependency;
import com.android.systemui.Flags;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor;
+import com.android.systemui.omni.OmniSettingsService;
import com.android.systemui.modes.shared.ModesUiIcons;
import com.android.systemui.privacy.PrivacyItem;
import com.android.systemui.privacy.PrivacyItemController;
@@ -86,6 +102,8 @@
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.DateFormatUtil;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
@@ -107,7 +125,8 @@
KeyguardStateController.Callback,
PrivacyItemController.Callback,
LocationController.LocationChangeCallback,
- RecordingController.RecordingStateChangeCallback {
+ RecordingController.RecordingStateChangeCallback,
+ OmniSettingsService.OmniSettingsObserver {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -175,6 +194,9 @@
private BluetoothController mBluetooth;
private AlarmManager.AlarmClockInfo mNextAlarm;
+ private Context mContext;
+ private boolean mShowAlarm;
+ private boolean mShowBtBattery;
@Inject
public PhoneStatusBarPolicy(StatusBarIconController iconController,
@@ -198,7 +220,8 @@
PrivacyLogger privacyLogger,
ConnectedDisplayInteractor connectedDisplayInteractor,
ZenModeInteractor zenModeInteractor,
- JavaAdapter javaAdapter
+ JavaAdapter javaAdapter,
+ Context context
) {
mIconController = iconController;
mCommandQueue = commandQueue;
@@ -231,6 +254,7 @@
mPrivacyLogger = privacyLogger;
mZenModeInteractor = zenModeInteractor;
mJavaAdapter = javaAdapter;
+ mContext = context;
mSlotCast = resources.getString(com.android.internal.R.string.status_bar_cast);
mSlotConnectedDisplay = resources.getString(
@@ -265,6 +289,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
+ filter.addAction(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED);
filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
@@ -387,6 +412,8 @@
}
mJavaAdapter.alwaysCollectFlow(mConnectedDisplayInteractor.getConnectedDisplayState(),
this::onConnectedDisplayAvailabilityChanged);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this, OmniSettings.OMNI_STATUS_BAR_ALARM);
+ Dependency.get(OmniSettingsService.class).addIntObserver(this, OmniSettings.OMNI_STATUS_BAR_BT_BATTERY);
mCommandQueue.addCallback(this);
}
@@ -438,11 +465,10 @@
private void updateAlarm() {
final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(mUserTracker.getUserId());
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
- int zen = mZenController.getZen();
- final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ final boolean zenNone = !zenAllowsAlarm();
mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
: R.drawable.stat_sys_alarm, buildAlarmContentDescription());
- mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
+ mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm && mShowAlarm);
}
private String buildAlarmContentDescription() {
@@ -543,17 +569,48 @@
String contentDescription =
mResources.getString(R.string.accessibility_quick_settings_bluetooth_on);
boolean bluetoothVisible = false;
+ StatusBarIcon icon = null;
if (mBluetooth != null) {
if (mBluetooth.isBluetoothConnected()
&& (mBluetooth.isBluetoothAudioActive()
|| !mBluetooth.isBluetoothAudioProfileOnly())) {
contentDescription = mResources.getString(
R.string.accessibility_bluetooth_connected);
+ }
+
+ if (mBluetooth.isBluetoothConnected()) {
+ final List<CachedBluetoothDevice> devices = mBluetooth.getConnectedDevices();
+ if (mShowBtBattery && devices != null) {
+ // get battery level for the first device with battery level support
+ for (CachedBluetoothDevice device : devices) {
+ // don't get the level if still pairing
+ int state = device.getMaxConnectionState();
+ if (state == BluetoothProfile.STATE_CONNECTED) {
+ int batteryLevel = device.getBatteryLevel();
+ contentDescription = mResources.getString(R.string.accessibility_bluetooth_connected);
+ if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
+ final int padding = mResources.getDimensionPixelSize(com.android.settingslib.R.dimen.bt_battery_padding);
+ Drawable d = BluetoothDeviceLayerDrawable.createLayerDrawable(mContext,
+ R.drawable.ic_bluetooth_connected, batteryLevel, 1, -padding, padding, 0);
+ icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithBitmap(getBitmapFromDrawable(d)), 0, 0, contentDescription,
+ StatusBarIcon.Type.SystemIcon);
+ } else {
+ iconId = R.drawable.stat_sys_data_bluetooth_connected;
+ }
+ break;
+ }
+ }
+ }
bluetoothVisible = mBluetooth.isBluetoothEnabled();
}
}
- mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
+ if (icon != null) {
+ mIconController.setCustomIcon(mSlotBluetooth, icon);
+ } else {
+ mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
+ }
mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
}
@@ -851,6 +908,9 @@
case AudioManager.ACTION_HEADSET_PLUG:
updateHeadsetPlug(intent);
break;
+ case BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED:
+ updateBluetooth();
+ break;
}
}
};
@@ -943,4 +1003,43 @@
mIconController.setIconVisibility(mSlotConnectedDisplay, visible);
}
+
+ @Override
+ public void onIntSettingChanged(String key, Integer newValue) {
+ mShowAlarm = System.getIntForUser(mContext.getContentResolver(),
+ OmniSettings.OMNI_STATUS_BAR_ALARM, 0, mUserTracker.getUserId()) != 0;
+ updateAlarm();
+ mShowBtBattery = System.getIntForUser(mContext.getContentResolver(),
+ OmniSettings.OMNI_STATUS_BAR_BT_BATTERY, 0, mUserTracker.getUserId()) != 0;
+ updateBluetooth();
+ }
+
+ private boolean zenAllowsAlarm() {
+ int zen = mZenController.getZen();
+ if (zen == Global.ZEN_MODE_OFF) {
+ return true;
+ }
+ if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ return false;
+ }
+ if (zen == Global.ZEN_MODE_ALARMS) {
+ return true;
+ }
+ boolean allowAlarms = (mZenController.getConsolidatedPolicy().priorityCategories & NotificationManager.Policy
+ .PRIORITY_CATEGORY_ALARMS) != 0;
+ return allowAlarms;
+ }
+
+ private Bitmap getBitmapFromDrawable(Drawable image) {
+ final Canvas canvas = new Canvas();
+ canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.ANTI_ALIAS_FLAG,
+ Paint.FILTER_BITMAP_FLAG));
+
+ Bitmap bmResult = Bitmap.createBitmap(image.getIntrinsicWidth(), image.getIntrinsicHeight(),
+ Bitmap.Config.ARGB_8888);
+ canvas.setBitmap(bmResult);
+ image.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+ image.draw(canvas);
+ return bmResult;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java
index 0459b97..4edc42c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java
@@ -61,6 +61,11 @@
void setIcon(String slot, int resourceId, CharSequence contentDescription);
/**
+ * @hide
+ */
+ void setCustomIcon(String slot, StatusBarIcon icon);
+
+ /**
* Adds or updates an icon for the given slot.
*
* @param resPackage the package name containing the resource in question. Can be null if the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
index e66e8138..f6c06c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
@@ -293,6 +293,17 @@
}
@Override
+ public void setCustomIcon(String slot, StatusBarIcon icon) {
+ if (icon == null) {
+ removeAllIconsForSlot(slot, /* fromNewPipeline */ false);
+ return;
+ }
+
+ StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
+ setIcon(slot, holder);
+ }
+
+ @Override
public void setNewWifiIcon() {
String slot = mContext.getString(com.android.internal.R.string.status_bar_wifi);
StatusBarIconHolder holder = mStatusBarIconList.getIconHolder(slot, /* tag= */ 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 279e5ef..f7f38aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -24,6 +24,7 @@
void setFlashlight(boolean newState);
boolean isAvailable();
boolean isEnabled();
+ void initFlashLight();
@WeaklyReferencedCallback
public interface FlashlightListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 615cc74..ca77397 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -121,6 +121,12 @@
}
}
+ public synchronized void initFlashLight() {
+ if (mCameraId == null) {
+ tryInitCamera();
+ }
+ }
+
public void setFlashlight(boolean enabled) {
if (!mHasFlashlight) return;
if (mCameraId.get() == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 28cf78f..6df3a5e 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -801,12 +801,6 @@
mActivityManager.setThemeOverlayReady(currentUser);
};
- if (colorSchemeIsApplied(managedProfiles)) {
- Log.d(TAG, "Skipping overlay creation. Theme was already: " + mColorScheme);
- onCompleteCallback.run();
- return;
- }
-
if (DEBUG) {
Log.d(TAG, "Applying overlays: " + categoryToPackage.keySet().stream()
.map(key -> key + " -> " + categoryToPackage.get(key)).collect(
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 8a6f79d..35c6de7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -88,6 +88,7 @@
isTv(context)
? NotificationManager.IMPORTANCE_DEFAULT
: NotificationManager.IMPORTANCE_LOW);
+ storage.setBlockable(true);
final NotificationChannel hint = new NotificationChannel(
HINTS,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index a4e46f6..84db887 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -888,18 +888,22 @@
final LayerDrawable seekbarDrawable =
(LayerDrawable) mContext.getDrawable(R.drawable.volume_row_seekbar);
+ final LayerDrawable seekbarThumbDrawable =
+ (LayerDrawable) mContext.getDrawable(R.drawable.volume_row_seekbar_thumb);
+
final LayerDrawable seekbarProgressDrawable = (LayerDrawable)
((RoundedCornerProgressDrawable) seekbarDrawable.findDrawableByLayerId(
android.R.id.progress)).getDrawable();
row.sliderProgressSolid = seekbarProgressDrawable.findDrawableByLayerId(
R.id.volume_seekbar_progress_solid);
- final Drawable sliderProgressIcon = seekbarProgressDrawable.findDrawableByLayerId(
+ final Drawable sliderProgressIcon = seekbarThumbDrawable.findDrawableByLayerId(
R.id.volume_seekbar_progress_icon);
row.sliderProgressIcon = sliderProgressIcon != null ? (AlphaTintDrawableWrapper)
((RotateDrawable) sliderProgressIcon).getDrawable() : null;
row.slider.setProgressDrawable(seekbarDrawable);
+ row.slider.setThumb(seekbarThumbDrawable);
row.icon = row.view.findViewById(R.id.volume_row_icon);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 7ac7859..e0bb98c 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7444,5 +7444,8 @@
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
+
+ // ACTION: Custom Omni metrics
+ CUSTOM_QUICK_TILES = 9001;
}
}
diff --git a/services/Android.bp b/services/Android.bp
index 7298f14..20aa00c 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -323,6 +323,7 @@
"service-permission.stubs.system_server",
"service-rkp.stubs.system_server",
"service-sdksandbox.stubs.system_server",
+ "omnirom.internal",
],
soong_config_variables: {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
index ce9130a..c1bfb7a 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
@@ -117,7 +117,7 @@
out.attributeInt(null, ATTR_WIDGET_FEATURES, info.widgetFeatures);
out.attributeInt(null, ATTR_DESCRIPTION_RES, info.descriptionRes);
out.attributeBoolean(null, ATTR_PROVIDER_INHERITANCE, info.isExtendedFromAppWidgetProvider);
- out.attribute(null, ATTR_OS_FINGERPRINT, Build.FINGERPRINT);
+ out.attribute(null, ATTR_OS_FINGERPRINT, String.valueOf(Build.TIME));
}
/**
@@ -128,7 +128,7 @@
@NonNull final TypedXmlPullParser parser) {
Objects.requireNonNull(parser);
final String fingerprint = parser.getAttributeValue(null, ATTR_OS_FINGERPRINT);
- if (!Build.FINGERPRINT.equals(fingerprint)) {
+ if (!String.valueOf(Build.TIME).equals(fingerprint)) {
return null;
}
final AppWidgetProviderInfo info = new AppWidgetProviderInfo();
diff --git a/services/core/Android.bp b/services/core/Android.bp
index b3d85f8..7a583a4 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -216,6 +216,7 @@
"icu4j_calendar_astronomer",
"android.security.aaid_aidl-java",
"netd-client",
+ "omnirom.internal",
"overlayable_policy_aidl-java",
"SurfaceFlingerProperties",
"com.android.sysprop.watchdog",
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 4cf17ae..bfd8790 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -82,6 +82,8 @@
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -350,6 +352,27 @@
private MetricsLogger mMetricsLogger;
+ //Battery light color customization
+ private boolean mLightEnabled = false;
+ private boolean mAllowBatteryLightOnDnd;
+ private boolean mIsDndActive;
+ private boolean mMultiColorLed;
+ private boolean mLightOnlyFullyCharged;
+ private boolean mFastChargingLedSupported;
+ private boolean mFastBatteryLightEnabled;
+ private int mBatteryLowARGB;
+ private int mBatteryMediumARGB;
+ private int mBatteryFullARGB;
+ private int mBatteryReallyFullARGB;
+ private int mFastBatteryARGB;
+ private int mBatteryLowBehavior;
+ private int mBatteryLowBehaviorCustom;
+
+ // TODO - thats a resource constant in SystemUI - maybe better
+ // move those into core context
+ private static final int FAST_CHARGING_ENABLED_THRESHOLD = 7500000;
+ private static final int DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT = 5000000;
+
private static final int MSG_BROADCAST_BATTERY_CHANGED = 1;
private static final int MSG_BROADCAST_POWER_CONNECTION_CHANGED = 2;
private static final int MSG_BROADCAST_BATTERY_LOW_OKAY = 3;
@@ -456,6 +479,8 @@
com.android.internal.R.bool.config_shutdownIfNoPower);
sSystemUiPackage = mContext.getResources().getString(
com.android.internal.R.string.config_systemUi);
+ mFastChargingLedSupported = context.getResources().getBoolean(
+ org.omnirom.omnilib.R.bool.config_FastChargingLedSupported);
mBatteryLevelsEventQueue = new ArrayDeque<>();
mMetricsLogger = new MetricsLogger();
@@ -510,6 +535,114 @@
false, obs, UserHandle.USER_ALL);
updateBatteryWarningLevelLocked();
}
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ SettingsObserver mObserver = new SettingsObserver(new Handler());
+ mObserver.observe();
+ }
+ }
+
+ private synchronized void updateLed() {
+ mLed.updateLightsLocked();
+ }
+
+ class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+
+ // Battery light enabled
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_ENABLED),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_ALLOW_ON_DND),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_ONLY_FULLY_CHARGED),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_LOW_BATTERY_BEHAVIOR),
+ false, this, UserHandle.USER_ALL);
+ if (mMultiColorLed) {
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_LOW_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_MEDIUM_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_FULL_COLOR),
+ false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_BATTERY_LIGHT_REALLY_FULL_COLOR),
+ false, this, UserHandle.USER_ALL);
+
+ if (mFastChargingLedSupported) {
+ //Fast Charging LED
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_FAST_CHARGING_LED_ENABLED), false, this,
+ UserHandle.USER_ALL);
+ // Register observer if we have a device that supports fast charging
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_FAST_BATTERY_LIGHT_COLOR), false, this,
+ UserHandle.USER_ALL);
+ }
+ }
+ update();
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+
+ // Battery light enabled
+ mLightEnabled = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_ENABLED, 1,
+ UserHandle.USER_CURRENT) != 0;
+ mAllowBatteryLightOnDnd = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_ALLOW_ON_DND, 0,
+ UserHandle.USER_CURRENT) == 1;
+ mIsDndActive = Settings.Global.getInt(resolver,
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF)
+ != Settings.Global.ZEN_MODE_OFF;
+ mBatteryLowARGB = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_LOW_COLOR, 0xFFFF0000,
+ UserHandle.USER_CURRENT);
+ mBatteryMediumARGB = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_MEDIUM_COLOR, 0xFFFFFF00,
+ UserHandle.USER_CURRENT);
+ mBatteryFullARGB = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_FULL_COLOR, 0xFFFFFF00,
+ UserHandle.USER_CURRENT);
+ mBatteryReallyFullARGB = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_REALLY_FULL_COLOR, 0xFF00FF00,
+ UserHandle.USER_CURRENT);
+ mFastBatteryLightEnabled = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_FAST_CHARGING_LED_ENABLED, 0,
+ UserHandle.USER_CURRENT) != 0;
+ mFastBatteryARGB = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_FAST_BATTERY_LIGHT_COLOR,
+ mContext.getResources().getInteger(
+ org.omnirom.omnilib.R.integer.config_notificationsFastBatteryARGB),
+ UserHandle.USER_CURRENT);
+ mLightOnlyFullyCharged = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_BATTERY_LIGHT_ONLY_FULLY_CHARGED, 0,
+ UserHandle.USER_CURRENT) != 0;
+ mBatteryLowBehaviorCustom = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_LOW_BATTERY_BEHAVIOR, 0,
+ UserHandle.USER_CURRENT);
+
+ updateLed();
}
}
@@ -998,6 +1131,29 @@
mLastBroadcastBatteryCycleCount = mHealthInfo.batteryCycleCount;
mLastBroadcastChargingState = mHealthInfo.chargingState;
mLastBroadcastBatteryCapacityLevel = mHealthInfo.batteryCapacityLevel;
+
+ final int maxChargingMicroWatt;
+ if (mLastMaxChargingVoltage <= 0) {
+ mLastMaxChargingVoltage = DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT;
+ }
+ if (mLastMaxChargingCurrent > 0) {
+ // Calculating muW = muA * muV / (10^6 mu^2 / mu); splitting up the divisor
+ // to maintain precision equally on both factors.
+ maxChargingMicroWatt = (mLastMaxChargingCurrent / 1000)
+ * (mLastMaxChargingVoltage / 1000);
+ } else {
+ maxChargingMicroWatt = -1;
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, "mLastMaxChargingCurrent = " + mLastMaxChargingCurrent +
+ " mLastMaxChargingVoltage = " + mLastMaxChargingVoltage +
+ " maxChargingMicroWatt = " + maxChargingMicroWatt);
+ }
+ if (mFastChargingLedSupported) {
+ // Update the Fast battery LED
+ mLed.fastCharge(maxChargingMicroWatt);
+ }
}
}
}
@@ -1748,22 +1904,24 @@
private final LogicalLight mBatteryLight;
- private final int mBatteryLowARGB;
- private final int mBatteryMediumARGB;
- private final int mBatteryFullARGB;
private final int mBatteryLedOn;
private final int mBatteryLedOff;
- private final int mBatteryLowBehavior;
+ private boolean mIsFastCharging;
+
+ protected void fastCharge(int maxChargingMicroWatt) {
+ mIsFastCharging = maxChargingMicroWatt > FAST_CHARGING_ENABLED_THRESHOLD;
+ if (DEBUG) {
+ Slog.d(TAG, "mIsFastCharging = " + mIsFastCharging);
+ }
+ updateLightsLocked();
+ }
public Led(Context context, LightsManager lights) {
mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
- mBatteryLowARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryLowARGB);
- mBatteryMediumARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryMediumARGB);
- mBatteryFullARGB = context.getResources().getInteger(
- com.android.internal.R.integer.config_notificationsBatteryFullARGB);
+ // Does the Device support changing battery LED colors?
+ mMultiColorLed = context.getResources().getBoolean(
+ org.omnirom.omnilib.R.bool.config_multiColorBatteryLed);
mBatteryLedOn = context.getResources().getInteger(
com.android.internal.R.integer.config_notificationsBatteryLedOn);
mBatteryLedOff = context.getResources().getInteger(
@@ -1781,25 +1939,41 @@
if (mBatteryLight == null) {
return;
}
+ // mHealthInfo could be null on startup (called by SettingsObserver)
+ if (mHealthInfo == null) {
+ Slog.w(TAG, "updateLightsLocked: mHealthInfo is null; skipping");
+ return;
+ }
final int level = mHealthInfo.batteryLevel;
final int status = mHealthInfo.batteryStatus;
- if (level < mLowBatteryWarningLevel) {
+ boolean fastlightenabled = mFastBatteryLightEnabled & mIsFastCharging;
+ if (!mLightEnabled || (mIsDndActive && !mAllowBatteryLightOnDnd)) {
+ mBatteryLight.turnOff();
+ } else if (level < mLowBatteryWarningLevel) {
+ if (mContext.getResources().getBoolean(
+ org.omnirom.omnilib.R.bool.config_intrusiveBatteryLed)) {
+ mBatteryLowBehavior = mBatteryLowBehaviorCustom;
+ }
switch (mBatteryLowBehavior) {
case LOW_BATTERY_BEHAVIOR_SOLID:
- // Solid red when low battery
+ // Solid color when low battery
mBatteryLight.setColor(mBatteryLowARGB);
break;
case LOW_BATTERY_BEHAVIOR_FLASHING:
- // Flash red when battery is low and not charging
+ // Flash when battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
mBatteryLedOn, mBatteryLedOff);
break;
default:
- if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
- // Solid red when battery is charging
+ if (fastlightenabled) {
+ //Solid color when battery is fast charging
+ mBatteryLight.setColor(mFastBatteryARGB);
+ mLightEnabled = !mLightOnlyFullyCharged;
+ } else if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+ // Solid when battery is charging
mBatteryLight.setColor(mBatteryLowARGB);
} else {
- // Flash red when battery is low and not charging
+ // Flash when battery is low and not charging
mBatteryLight.setFlashing(mBatteryLowARGB,
LogicalLight.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff);
}
@@ -1809,11 +1983,23 @@
|| status == BatteryManager.BATTERY_STATUS_FULL) {
if (status == BatteryManager.BATTERY_STATUS_FULL
|| level >= mBatteryNearlyFullLevel) {
- // Solid green when full or charging and nearly full
- mBatteryLight.setColor(mBatteryFullARGB);
+ if (level == 100) {
+ // Battery is really full
+ mBatteryLight.setColor(mBatteryReallyFullARGB);
+ } else {
+ // Battery is full or charging and nearly full
+ mBatteryLight.setColor(mBatteryFullARGB);
+ }
} else {
- // Solid orange when charging and halfway full
- mBatteryLight.setColor(mBatteryMediumARGB);
+ if (fastlightenabled) {
+ //Solid color when battery is fast charging
+ mBatteryLight.setColor(mFastBatteryARGB);
+ mLightEnabled = !mLightOnlyFullyCharged;
+ } else {
+ // Battery is charging and halfway full
+ mLightEnabled = !mLightOnlyFullyCharged;
+ mBatteryLight.setColor(mBatteryMediumARGB);
+ }
}
} else {
// No lights if not charging and not low
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index ccc44a4..de0a2b3 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -700,6 +700,14 @@
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
}
+ /**
+ * @return true if camera was launched, false otherwise.
+ * @hide
+ */
+ public boolean doCameraLaunchGesture() {
+ return handleCameraGesture(false, StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
+ }
+
private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b7bc4e4..0f1f09c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1634,7 +1634,7 @@
// Adoptable public disks are visible to apps, since they meet
// public API requirement of being in a stable location.
- if (vol.disk.isAdoptable()) {
+ if (vol.disk.isAdoptable() || vol.disk.isSd()) {
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 0c04be1..d447a6c 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -1073,6 +1073,18 @@
}
@Override // Binder call
+ public boolean isDozing() {
+ checkPermission(android.Manifest.permission.READ_DREAM_STATE);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isDozingInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public boolean isDreamingOrInPreview() {
checkPermission(android.Manifest.permission.READ_DREAM_STATE);
@@ -1333,6 +1345,11 @@
}
@Override
+ public boolean isDozing() {
+ return isDozingInternal();
+ }
+
+ @Override
public boolean canStartDreaming(boolean isScreenOn) {
return canStartDreamingInternal(isScreenOn);
}
diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java
index fee54f5..92ac6e2 100644
--- a/services/core/java/com/android/server/logcat/LogcatManagerService.java
+++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java
@@ -435,6 +435,11 @@
return;
}
+ if (client.mPackageName.equals("org.omnirom.logcat")) {
+ onAccessApprovedForClient(client);
+ return;
+ }
+
if (!shouldShowConfirmationDialog(client)) {
onAccessDeclinedForClient(client);
return;
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 0e9ec4d..3028977 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -822,7 +822,8 @@
// Idmaps for immutable RROs targeting "android", i.e. framework-res.apk, are created at
// boot time in OverlayConfig.createImmutableFrameworkIdmapsInZygote().
- if (targetPackage != null && !("android".equals(info.getTargetPackageName())
+ if (targetPackage != null && !(("android".equals(info.getTargetPackageName()) ||
+ "omnirom.platform".equals(info.getTargetPackageName()))
&& !isPackageConfiguredMutable(overlayPackage))) {
idmapStatus = mIdmapManager.createIdmap(targetPackage, overlayPackageState,
overlayPackage, updatedOverlayInfo.baseCodePath, overlay.getOverlayName(),
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index be2f58d..c1c263b 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -169,6 +169,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -440,6 +441,16 @@
return mLocalAndroidApplication;
}
+ /**
+ * The Google signature faked by microG.
+ */
+ private static final String MICROG_FAKE_SIGNATURE = "308204433082032ba003020102020900c2e08746644a308d300d06092a864886f70d01010405003074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f6964301e170d3038303832313233313333345a170d3336303130373233313333345a3074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f696430820120300d06092a864886f70d01010105000382010d00308201080282010100ab562e00d83ba208ae0a966f124e29da11f2ab56d08f58e2cca91303e9b754d372f640a71b1dcb130967624e4656a7776a92193db2e5bfb724a91e77188b0e6a47a43b33d9609b77183145ccdf7b2e586674c9e1565b1f4c6a5955bff251a63dabf9c55c27222252e875e4f8154a645f897168c0b1bfc612eabf785769bb34aa7984dc7e2ea2764cae8307d8c17154d7ee5f64a51a44a602c249054157dc02cd5f5c0e55fbef8519fbe327f0b1511692c5a06f19d18385f5c4dbc2d6b93f68cc2979c70e18ab93866b3bd5db8999552a0e3b4c99df58fb918bedc182ba35e003c1b4b10dd244a8ee24fffd333872ab5221985edab0fc0d0b145b6aa192858e79020103a381d93081d6301d0603551d0e04160414c77d8cc2211756259a7fd382df6be398e4d786a53081a60603551d2304819e30819b8014c77d8cc2211756259a7fd382df6be398e4d786a5a178a4763074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f6964820900c2e08746644a308d300c0603551d13040530030101ff300d06092a864886f70d010104050003820101006dd252ceef85302c360aaace939bcff2cca904bb5d7a1661f8ae46b2994204d0ff4a68c7ed1a531ec4595a623ce60763b167297a7ae35712c407f208f0cb109429124d7b106219c084ca3eb3f9ad5fb871ef92269a8be28bf16d44c8d9a08e6cb2f005bb3fe2cb96447e868e731076ad45b33f6009ea19c161e62641aa99271dfd5228c5c587875ddb7f452758d661f6cc0cccb7352e424cc4365c523532f7325137593c4ae341f4db41edda0d0b1071a7c440f0fe9ea01cb627ca674369d084bd2fd911ff06cdbf2cfa10dc0f893ae35762919048c7efc64c7144178342f70581c9de573af55b390dd7fdb9418631895d5f759f30112687ff621410c069308a";
+
+ /**
+ * List of packages which require signature spoofing.
+ */
+ private static final List<String> MICROG_FAKE_SIGNATURE_PACKAGES = List.of("com.google.android.gms", "com.android.vending");
+
ComputerEngine(PackageManagerService.Snapshot args, int version) {
mVersion = version;
mSettings = new Settings(args.settings);
@@ -1511,23 +1522,53 @@
// Compute GIDs only if requested
final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY
: mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.getAppId()));
+
+ // Allow microG GmsCore and FakeStore to spoof signature
+ final boolean isMicroG = MICROG_FAKE_SIGNATURE_PACKAGES.contains(p.getPackageName());
+
+ // OmniLib ressources overlay enabled by the ROM_BUILDTYPE MicroG
+ final boolean mUseMicroGBuildType = mContext.getResources().getBoolean(
+ org.omnirom.omnilib.R.bool.config_useMicroGBuildType);
+
// Compute installed permissions only if requested
final Set<String> installedPermissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
|| ArrayUtils.isEmpty(p.getPermissions())) ? Collections.emptySet()
: mPermissionManager.getInstalledPermissions(ps.getPackageName());
// Compute granted permissions only if package has requested permissions
- final Set<String> grantedPermissions = ((flags & PackageManager.GET_PERMISSIONS) == 0
- || ArrayUtils.isEmpty(p.getRequestedPermissions())) ? Collections.emptySet()
+ // or we matched a microg package
+ final Set<String> grantedPermissions = (((flags & PackageManager.GET_PERMISSIONS) == 0
+ || ArrayUtils.isEmpty(p.getRequestedPermissions())) && !isMicroG && !mUseMicroGBuildType ) ? Collections.emptySet()
: mPermissionManager.getGrantedPermissions(ps.getPackageName(), userId);
PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
state.getFirstInstallTimeMillis(), ps.getLastUpdateTime(), installedPermissions,
grantedPermissions, state, userId, ps);
+ if (isMicroG && mUseMicroGBuildType) {
+ packageInfo = mayFakeSignature(p, packageInfo, grantedPermissions);
+ }
+
if (packageInfo == null) {
return null;
}
+ if (isMicroG && mUseMicroGBuildType) {
+ if (grantedPermissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")) {
+ try {
+ packageInfo.signingInfo = new SigningInfo(
+ new SigningDetails(
+ packageInfo.signatures,
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
+ SigningDetails.toSigningKeys(packageInfo.signatures),
+ null
+ )
+ );
+ } catch (CertificateException e) {
+ Slog.e(TAG, "Caught an exception when creating signing keys: ", e);
+ }
+ }
+ }
+
packageInfo.packageName = packageInfo.applicationInfo.packageName =
resolveExternalPackageName(p);
@@ -1578,6 +1619,21 @@
}
}
+ private PackageInfo mayFakeSignature(AndroidPackage p, PackageInfo pi,
+ Set<String> permissions) {
+ try {
+ if (permissions.contains("android.permission.FAKE_PACKAGE_SIGNATURE")) {
+ if (pi != null) {
+ pi.signatures = new Signature[] {new Signature(MICROG_FAKE_SIGNATURE)};
+ }
+ }
+ } catch (Throwable t) {
+ // We should never die because of any failures, this is system code!
+ Log.w("PackageManagerService.FAKE_PACKAGE_SIGNATURE", t);
+ }
+ return pi;
+ }
+
public final PackageInfo getPackageInfo(String packageName,
@PackageManager.PackageInfoFlagsBits long flags, int userId) {
return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index aadf112..24a56b7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2239,7 +2239,7 @@
if (mIsUpgrade) {
PackageManagerServiceUtils.logCriticalInfo(Log.INFO,
"Upgrading from " + ver.fingerprint + " (" + ver.buildFingerprint + ") to "
- + PackagePartitions.FINGERPRINT + " (" + Build.FINGERPRINT + ")");
+ + PackagePartitions.FINGERPRINT + " (" + String.valueOf(Build.TIME) + ")");
}
mPriorSdkVersion = mIsUpgrade ? ver.sdkVersion : -1;
mInitAppsHelper = new InitAppsHelper(this, mApexManager, mInstallPackageHelper,
@@ -2397,7 +2397,7 @@
| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
}
}
- ver.buildFingerprint = Build.FINGERPRINT;
+ ver.buildFingerprint = String.valueOf(Build.TIME);
ver.fingerprint = PackagePartitions.FINGERPRINT;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 7af39f7..a297d90 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -1399,9 +1399,7 @@
// NOTE: When no BUILD_NUMBER is set by the build system, it defaults to a build
// that starts with "eng." to signify that this is an engineering build and not
// destined for release.
- if (isUserDebugBuild && incrementalVersion.startsWith("eng.")) {
- Slog.w(TAG, "Wiping cache directory because the system partition changed.");
-
+ /*if (isUserDebugBuild && incrementalVersion.startsWith("eng.")) {
// Heuristic: If the /system directory has been modified recently due to an "adb sync"
// or a regular make, then blow away the cache. Note that mtimes are *NOT* reliable
// in general and should not be used for production changes. In this specific case,
@@ -1409,10 +1407,11 @@
File frameworkDir =
new File(Environment.getRootDirectory(), "framework");
if (cacheDir.lastModified() < frameworkDir.lastModified()) {
+ Slog.w(TAG, "Wiping cache directory because the system partition changed.");
FileUtils.deleteContents(cacheBaseDir);
cacheDir = FileUtils.createDir(cacheBaseDir, cacheName);
}
- }
+ }*/
return cacheDir;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 485a280..01f9ca8 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -485,7 +485,7 @@
public void forceCurrent() {
sdkVersion = Build.VERSION.SDK_INT;
databaseVersion = CURRENT_DATABASE_VERSION;
- buildFingerprint = Build.FINGERPRINT;
+ buildFingerprint = String.valueOf(Build.TIME);
fingerprint = PackagePartitions.FINGERPRINT;
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 1052c94..90555a5 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -5259,7 +5259,7 @@
// Injection point.
String injectBuildFingerprint() {
- return Build.FINGERPRINT;
+ return String.valueOf(Build.TIME);
}
final void wtf(String message) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8052754..c318eec 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -154,6 +154,10 @@
import android.hardware.input.InputManager;
import android.hardware.input.InputSettings;
import android.hardware.input.KeyGestureEvent;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
@@ -217,6 +221,11 @@
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillManagerInternal;
import android.widget.Toast;
+import org.omnirom.omnilib.utils.DeviceKeyHandler;
+import org.omnirom.omnilib.utils.OmniSettings;
+import org.omnirom.omnilib.utils.OmniUtils;
+
+import dalvik.system.PathClassLoader;
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
@@ -263,6 +272,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -281,6 +291,7 @@
static final boolean localLOGV = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_KEYGUARD = false;
+ static final boolean DEBUG_PROXI_SENSOR = false;
static final boolean DEBUG_WAKEUP = false;
// Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
@@ -314,6 +325,7 @@
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4;
static final int LONG_PRESS_POWER_ASSISTANT = 5; // Settings.Secure.ASSISTANT
+ static final int LONG_PRESS_POWER_TORCH = 6;
// must match: config_veryLongPresOnPowerBehavior in config.xml
// The config value can be overridden using Settings.Global.POWER_BUTTON_VERY_LONG_PRESS
@@ -763,6 +775,18 @@
private static final int MSG_RINGER_TOGGLE_CHORD = 24;
private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
private static final int MSG_SET_DEFERRED_KEY_ACTIONS_EXECUTABLE = 27;
+ private static final int MSG_TOGGLE_TORCH = 28;
+
+ // omni additions start
+ private DeviceKeyHandler mDeviceKeyHandler;
+ private boolean mProxyIsNear;
+ private SensorManager mSensorManager;
+ private Sensor mProximitySensor;
+ private boolean mProxiWakeupCheckEnabled;
+ private boolean mProxiListenerEnabled;
+ private boolean mLongPressPowerTorch;
+
+ private static final int KEY_ACTION_TOGGLE_TORCH = 9;
private class PolicyHandler extends Handler {
@@ -858,6 +882,9 @@
final long downTime = (Long) msg.obj;
mDeferredKeyActionExecutor.setActionsExecutable(keyCode, downTime);
break;
+ case MSG_TOGGLE_TORCH:
+ performKeyAction(KEY_ACTION_TOGGLE_TORCH);
+ break;
}
}
}
@@ -943,6 +970,12 @@
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.NAV_BAR_KIDS_MODE), false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_SYSTEM_PROXI_CHECK_ENABLED), false, this,
+ UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_LONG_PRESS_POWER_TORCH), false, this,
+ UserHandle.USER_ALL);
updateSettings();
}
@@ -1099,7 +1132,9 @@
|| mKeyCombinationManager.isPowerKeyIntercepted();
if (!mPowerKeyHandled) {
if (!interactive) {
- wakeUpFromWakeKey(event);
+ if (!mLongPressPowerTorch) {
+ wakeUpFromWakeKey(event);
+ }
}
} else {
// handled by another power key policy.
@@ -1199,6 +1234,8 @@
break;
}
}
+ } else if (!mProxyIsNear && mLongPressPowerTorch && mSingleKeyGestureDetector.beganFromNonInteractive()) {
+ wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
}
}
@@ -1454,6 +1491,17 @@
launchAssistAction(null, powerKeyDeviceId, eventTime,
AssistUtils.INVOCATION_TYPE_POWER_BUTTON_LONG_PRESS);
break;
+ case LONG_PRESS_POWER_TORCH:
+ mPowerKeyHandled = true;
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
+ "Power - Long Press - Toggle Torch");
+ // Toggle torch state asynchronously to help protect against
+ // a misbehaving cameraservice from blocking systemui.
+ mHandler.removeMessages(MSG_TOGGLE_TORCH);
+ Message msg = mHandler.obtainMessage(MSG_TOGGLE_TORCH);
+ msg.setAsynchronous(true);
+ msg.sendToTarget();
+ break;
}
}
@@ -1516,6 +1564,9 @@
if (FactoryTest.isLongPressOnPowerOffEnabled()) {
return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
}
+ if (mLongPressPowerTorch && (!isScreenOn() || isDozeMode())) {
+ return LONG_PRESS_POWER_TORCH;
+ }
// If the config indicates the assistant behavior but the device isn't yet provisioned, show
// global actions instead.
@@ -2492,6 +2543,49 @@
initKeyGestures();
mButtonOverridePermissionChecker = injector.getButtonOverridePermissionChecker();
mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
+
+ String deviceKeyHandlerLib = mContext.getResources().getString(
+ org.omnirom.omnilib.R.string.config_deviceKeyHandlerLib);
+
+ String deviceKeyHandlerClass = mContext.getResources().getString(
+ org.omnirom.omnilib.R.string.config_deviceKeyHandlerClass);
+
+ if (!deviceKeyHandlerLib.isEmpty() && !deviceKeyHandlerClass.isEmpty()) {
+ try {
+ PathClassLoader loader = new PathClassLoader(deviceKeyHandlerLib,
+ getClass().getClassLoader());
+
+ Class<?> klass = loader.loadClass(deviceKeyHandlerClass);
+ Constructor<?> constructor = klass.getConstructor(Context.class);
+ mDeviceKeyHandler = (DeviceKeyHandler) constructor.newInstance(
+ mContext);
+ if(DEBUG_INPUT) Slog.d(TAG, "Device key handler loaded");
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not instantiate device key handler "
+ + deviceKeyHandlerClass + " from class "
+ + deviceKeyHandlerLib, e);
+ }
+ }
+ boolean supportPowerButtonProxyCheck = mContext.getResources().getBoolean(
+ org.omnirom.omnilib.R.bool.config_proxiSensorWakupCheck);
+ if (supportPowerButtonProxyCheck) {
+ mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ if (mDeviceKeyHandler != null && mDeviceKeyHandler.getCustomProxiSensor() != null) {
+ String proxySensor = mDeviceKeyHandler.getCustomProxiSensor();
+ for (Sensor sensor : mSensorManager.getSensorList(Sensor.TYPE_ALL)) {
+ if (proxySensor.equals(sensor.getStringType())) {
+ mProximitySensor = sensor;
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "mProximitySensor = " + proxySensor);
+ }
+ }
+ }
+ if (mProximitySensor == null) {
+ mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ if (mProximitySensor != null) {
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "mProximitySensor = Sensor.TYPE_PROXIMITY");
+ }
+ }
+ }
}
private void initKeyCombinationRules() {
@@ -2683,10 +2777,23 @@
@Override
void onLongPress(long eventTime) {
- if (mSingleKeyGestureDetector.beganFromNonInteractive()
- && !mSupportLongPressPowerWhenNonInteractive) {
- Slog.v(TAG, "Not support long press power when device is not interactive.");
- return;
+ if (mSingleKeyGestureDetector.beganFromNonInteractive() || isFlashLightIsOn()) {
+ if (mLongPressPowerTorch) {
+ if (!mProxyIsNear) {
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
+ "Power - Long Press - Torch");
+ performKeyAction(KEY_ACTION_TOGGLE_TORCH);
+ }
+ return;
+ }
+ if (!mSupportLongPressPowerWhenNonInteractive) {
+ Slog.v(TAG, "Not support long press power when device is not interactive.");
+ return;
+ }
+ if (mProxyIsNear) {
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "blocked onLongPress because of mProxyIsNear");
+ return;
+ }
}
powerLongPress(eventTime);
@@ -3087,6 +3194,13 @@
mKidsModeEnabled = kidsModeEnabled;
updateKidsModeSettings = true;
}
+
+ mProxiWakeupCheckEnabled = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_SYSTEM_PROXI_CHECK_ENABLED, 0,
+ UserHandle.USER_CURRENT) != 0;
+ mLongPressPowerTorch = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_LONG_PRESS_POWER_TORCH, 0,
+ UserHandle.USER_CURRENT) != 0;
}
if (updateKidsModeSettings) {
updateKidsModeSettings(kidsModeEnabled);
@@ -4053,6 +4167,18 @@
return true;
}
+ // Specific device key handling
+ if (mDeviceKeyHandler != null) {
+ try {
+ // The device only will consume known keys.
+ if (mDeviceKeyHandler.canHandleKeyEvent(event)) {
+ return true;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not dispatch event to device key handler", e);
+ }
+ }
+
// Reserve all the META modifier combos for system behavior
return (metaState & KeyEvent.META_META_ON) != 0;
}
@@ -5320,6 +5446,53 @@
&& (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
&& event.getRepeatCount() == 0;
+ // Specific device key handling
+ if (mDeviceKeyHandler != null) {
+ try {
+ // The device says if we should ignore this event.
+ if (mDeviceKeyHandler.isDisabledKeyEvent(event)) {
+ result &= ~ACTION_PASS_TO_USER;
+ return result;
+ }
+ if (mDeviceKeyHandler.isCameraLaunchEvent(event)) {
+ if (DEBUG_INPUT) {
+ Slog.i(TAG, "isCameraLaunchEvent from DeviceKeyHandler");
+ }
+ GestureLauncherService gestureService = LocalServices.getService(
+ GestureLauncherService.class);
+ if (gestureService != null) {
+ gestureService.doCameraLaunchGesture();
+ }
+ result &= ~ACTION_PASS_TO_USER;
+ return result;
+ }
+ if (!interactive && mDeviceKeyHandler.isWakeEvent(event)) {
+ if (DEBUG_INPUT) {
+ Slog.i(TAG, "isWakeEvent from DeviceKeyHandler");
+ }
+ wakeUpFromWakeKey(event);
+ result &= ~ACTION_PASS_TO_USER;
+ return result;
+ }
+ final Intent eventLaunchActivity = mDeviceKeyHandler.isActivityLaunchEvent(event);
+ if (!interactive && eventLaunchActivity != null) {
+ if (DEBUG_INPUT) {
+ Slog.i(TAG, "isActivityLaunchEvent from DeviceKeyHandler " + eventLaunchActivity);
+ }
+ wakeUpFromWakeKey(event);
+ OmniUtils.launchKeyguardDismissIntent(mContext, UserHandle.CURRENT, eventLaunchActivity);
+ result &= ~ACTION_PASS_TO_USER;
+ return result;
+ }
+ if (mDeviceKeyHandler.handleKeyEvent(event)) {
+ result &= ~ACTION_PASS_TO_USER;
+ return result;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Could not dispatch event to device key handler", e);
+ }
+ }
+
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_BACK: {
@@ -5471,6 +5644,10 @@
// Any activity on the power button stops the accessibility shortcut
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
+ if (mProxiListenerEnabled && mProxyIsNear) {
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "KeyEvent.KEYCODE_POWER blocked because of mProxyIsNear");
+ break;
+ }
if (down) {
interceptPowerKeyDown(event, interactiveAndAwake, isKeyGestureTriggered);
} else {
@@ -5833,6 +6010,10 @@
* is always considered a wake key.
*/
private boolean isWakeKeyWhenScreenOff(int keyCode) {
+ if (mProxiListenerEnabled && mProxyIsNear) {
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "isWakeKeyWhenScreenOff blocked because of mProxyIsNear - keyCode = " + keyCode);
+ return false;
+ }
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
@@ -5914,7 +6095,7 @@
IDreamManager dreamManager = getDreamManager();
try {
- if (dreamManager != null && dreamManager.isDreaming()) {
+ if (dreamManager != null && dreamManager.isDreaming() && !dreamManager.isDozing()) {
return true;
}
} catch (RemoteException e) {
@@ -6199,6 +6380,13 @@
if (mDisplayFoldController != null) {
mDisplayFoldController.finishedWakingUp();
}
+
+ if (mProxiWakeupCheckEnabled && mProximitySensor != null) {
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "unregisterListener");
+ mSensorManager.unregisterListener(mProximitySensorListener, mProximitySensor);
+ mProxyIsNear = false;
+ mProxiListenerEnabled = false;
+ }
}
private boolean shouldWakeUpWithHomeIntent() {
@@ -6276,6 +6464,14 @@
}
mDefaultDisplayRotation.updateOrientationListener();
reportScreenStateToVrManager(false);
+
+ if (mProxiWakeupCheckEnabled && mProximitySensor != null && !mProxiListenerEnabled) {
+ mProxyIsNear = false;
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "registerListener");
+ mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ mProxiListenerEnabled = true;
+ }
}
}
@@ -7644,4 +7840,57 @@
}
return false;
}
+
+ // omni additions start
+ private SensorEventListener mProximitySensorListener = new SensorEventListener() {
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (mDeviceKeyHandler != null && mDeviceKeyHandler.getCustomProxiSensor() != null) {
+ mProxyIsNear = mDeviceKeyHandler.getCustomProxiIsNear(event);
+ } else {
+ mProxyIsNear = event.values[0] < mProximitySensor.getMaximumRange();
+ }
+ if (DEBUG_PROXI_SENSOR) Log.i(TAG, "mProxyIsNear = " + mProxyIsNear);
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ };
+
+ private boolean isFlashLightIsOn() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.FLASHLIGHT_ENABLED, 0) != 0;
+ }
+
+ private boolean isDozeMode() {
+ IDreamManager dreamManager = getDreamManager();
+ try {
+ if (dreamManager != null && dreamManager.isDozing()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ return false;
+ }
+ return false;
+ }
+
+ private void performKeyAction(int behavior) {
+ if (DEBUG_INPUT){
+ Slog.d(TAG, "performKeyAction " + behavior);
+ }
+ switch (behavior) {
+ case KEY_ACTION_TOGGLE_TORCH: {
+ IStatusBarService service = getStatusBarService();
+ if (service != null) {
+ try {
+ service.toggleCameraFlash();
+ } catch (RemoteException e) {
+ // do nothing.
+ }
+ }
+ break;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index cc31bb1..290743d 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -256,6 +256,12 @@
public void reboot(boolean confirm);
public void rebootSafeMode(boolean confirm);
+ /** @hide */
+ void reboot(String reason, boolean confirm);
+
+ /** @hide */
+ void rebootCustom(String reason, boolean confirm);
+
/**
* Return the window manager lock needed to correctly call "Lw" methods.
*/
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 36bc0b9..79d5e1f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -146,6 +146,8 @@
import dalvik.annotation.optimization.NeverCompile;
+import org.omnirom.omnilib.utils.OmniSettings;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -727,6 +729,10 @@
}
}
+ // omni additions start
+ // doze on charge
+ private boolean mDozeOnChargeEnabled;
+
private final class PowerGroupWakefulnessChangeListener implements
PowerGroup.PowerGroupListener {
@GuardedBy("mLock")
@@ -1348,6 +1354,10 @@
}
private void systemReady() {
+ // set initial value
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ OmniSettings.OMNI_DOZE_ON_CHARGE_NOW, 0, UserHandle.USER_CURRENT);
+
synchronized (mLock) {
mSystemReady = true;
mDreamManager = getLocalService(DreamManagerInternal.class);
@@ -1476,6 +1486,12 @@
resolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DEVICE_DEMO_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_DOZE_ON_CHARGE_NOW),
+ false, mSettingsObserver, UserHandle.USER_ALL);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ OmniSettings.OMNI_DOZE_ON_CHARGE),
+ false, mSettingsObserver, UserHandle.USER_ALL);
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
@@ -1578,6 +1594,10 @@
mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 1;
mAlwaysOnEnabled = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ mDozeOnChargeEnabled = Settings.System.getIntForUser(resolver,
+ OmniSettings.OMNI_DOZE_ON_CHARGE, 0, UserHandle.USER_CURRENT) != 0;
+ Settings.System.putIntForUser(resolver, OmniSettings.OMNI_DOZE_ON_CHARGE_NOW,
+ mDozeOnChargeEnabled && mIsPowered ? 1 : 0, UserHandle.USER_CURRENT);
if (mSupportsDoubleTapWakeConfig) {
boolean doubleTapWakeEnabled = Settings.Secure.getIntForUser(resolver,
@@ -2645,6 +2665,11 @@
final boolean dockedOnWirelessCharger = mWirelessChargerDetector.update(
mIsPowered, mPlugType);
+ if (mDozeOnChargeEnabled) {
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ OmniSettings.OMNI_DOZE_ON_CHARGE_NOW, mIsPowered ? 1 : 0,
+ UserHandle.USER_CURRENT);
+ }
// Treat plugging and unplugging the devices as a user activity.
// Users find it disconcerting when they plug or unplug the device
// and it shuts off right away.
@@ -4028,7 +4053,7 @@
}
private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
- @Nullable final String reason, boolean wait) {
+ @Nullable final String reason, boolean wait, final boolean custom) {
if (PowerManager.REBOOT_USERSPACE.equals(reason)) {
if (!PowerManager.isRebootingUserspaceSupportedImpl()) {
throw new UnsupportedOperationException(
@@ -4054,7 +4079,11 @@
if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
ShutdownThread.rebootSafeMode(getUiContext(), confirm);
} else if (haltMode == HALT_MODE_REBOOT) {
- ShutdownThread.reboot(getUiContext(), reason, confirm);
+ if (custom) {
+ ShutdownThread.rebootCustom(getUiContext(), reason, confirm);
+ } else {
+ ShutdownThread.reboot(getUiContext(), reason, confirm);
+ }
} else {
ShutdownThread.shutdown(getUiContext(), reason, confirm);
}
@@ -6695,7 +6724,7 @@
ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
+ shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait, false);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -6715,7 +6744,29 @@
ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm, reason, wait);
+ shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm, reason, wait, false);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ /**
+ * Reboots the device with custom progress message.
+ *
+ * @param confirm If true, shows a reboot confirmation dialog.
+ * @param reason The reason for the reboot, or null if none.
+ * @param wait If true, this call waits for the reboot to complete and does not return.
+ */
+ @Override // Binder call
+ public void rebootCustom(boolean confirm, String reason, boolean wait) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+ if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait, true);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -6734,7 +6785,7 @@
ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait);
+ shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait, false);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index d209ea9..aceac87 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -95,6 +95,7 @@
private static boolean sIsStarted = false;
private static boolean mReboot;
+ private static boolean mRebootCustom;
private static boolean mRebootSafeMode;
private static boolean mRebootHasProgressBar;
private static String mReason;
@@ -161,6 +162,7 @@
*/
public static void shutdown(final Context context, String reason, boolean confirm) {
mReboot = false;
+ mRebootCustom = false;
mRebootSafeMode = false;
mReason = reason;
shutdownInner(context, confirm);
@@ -260,6 +262,22 @@
mRebootSafeMode = false;
mRebootHasProgressBar = false;
mReason = reason;
+ mRebootCustom = false;
+ shutdownInner(context, confirm);
+ }
+
+ /**
+ * Request reboot system, reboot recovery or reboot bootloader
+ *
+ * @param context Context used to display the shutdown progress dialog.
+ * @param reason code to pass to the kernel (e.g. "recovery", "bootloader"), or null.
+ * @param confirm true if user confirmation is needed before rebooting.
+ */
+ public static void rebootCustom(final Context context, String reason, boolean confirm) {
+ mReboot = true;
+ mRebootSafeMode = false;
+ mReason = reason;
+ mRebootCustom = true;
shutdownInner(context, confirm);
}
@@ -278,6 +296,7 @@
}
mReboot = true;
+ mRebootCustom = false;
mRebootSafeMode = true;
mRebootHasProgressBar = false;
mReason = null;
@@ -339,20 +358,54 @@
com.android.internal.R.string.reboot_to_update_reboot));
}
} else if (mReason != null && mReason.equals(PowerManager.REBOOT_RECOVERY)) {
- if (CrashRecoveryHelper.isRecoveryTriggeredReboot()) {
- // We're not actually doing a factory reset yet; we're rebooting
- // to ask the user if they'd like to reset, so give them a less
- // scary dialog message.
- pd.setTitle(context.getText(com.android.internal.R.string.power_off));
- pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
- pd.setIndeterminate(true);
- } else if (showSysuiReboot()) {
- return null;
- } else {
- // Factory reset path. Set the dialog message accordingly.
- pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
+ if (!mRebootCustom) {
+ if (CrashRecoveryHelper.isRecoveryTriggeredReboot()) {
+ // We're not actually doing a factory reset yet; we're rebooting
+ // to ask the user if they'd like to reset, so give them a less
+ // scary dialog message.
+ pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+ pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ pd.setIndeterminate(true);
+ } else if (showSysuiReboot()) {
+ return null;
+ } else {
+ // Factory reset path. Set the dialog message accordingly.
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
+ pd.setMessage(context.getText(
+ com.android.internal.R.string.reboot_to_reset_message));
+ pd.setIndeterminate(true);
+ }
+ } else if (mReason != null && PowerManager.REBOOT_BOOTLOADER.equals(mReason) && mRebootCustom) {
+ if (showSysuiReboot()) {
+ return null;
+ }
+ pd.setTitle(context.getText(org.omnirom.omnilib.R.string.reboot_to_bootloader_title));
pd.setMessage(context.getText(
- com.android.internal.R.string.reboot_to_reset_message));
+ org.omnirom.omnilib.R.string.reboot_to_bootloader_message));
+ pd.setIndeterminate(true);
+ } else if (mReason != null && PowerManager.REBOOT_FASTBOOT.equals(mReason) && mRebootCustom) {
+ if (showSysuiReboot()) {
+ return null;
+ }
+ pd.setTitle(context.getText(org.omnirom.omnilib.R.string.reboot_to_fastboot_title));
+ pd.setMessage(context.getText(
+ org.omnirom.omnilib.R.string.reboot_to_fastboot_message));
+ pd.setIndeterminate(true);
+ } else if (mReason == null && mRebootCustom) {
+ if (showSysuiReboot()) {
+ return null;
+ }
+ pd.setTitle(context.getText(org.omnirom.omnilib.R.string.reboot_system_title));
+ pd.setMessage(context.getText(
+ org.omnirom.omnilib.R.string.reboot_system_message));
+ pd.setIndeterminate(true);
+ } else {
+ if (showSysuiReboot()) {
+ return null;
+ }
+ pd.setTitle(context.getText(org.omnirom.omnilib.R.string.reboot_to_recovery_title));
+ pd.setMessage(context.getText(
+ org.omnirom.omnilib.R.string.reboot_to_recovery_message));
pd.setIndeterminate(true);
}
} else {
@@ -377,7 +430,7 @@
try {
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
- if (service.showShutdownUi(mReboot, mReason)) {
+ if (service.showShutdownUi(mReboot, mReason, mRebootCustom)) {
// Sysui will handle shutdown UI.
if (DEBUG) {
Log.d(TAG, "SysUI handling shutdown UI");
diff --git a/services/core/java/com/android/server/statusbar/SessionMonitor.java b/services/core/java/com/android/server/statusbar/SessionMonitor.java
index f4356bd..321ee67 100644
--- a/services/core/java/com/android/server/statusbar/SessionMonitor.java
+++ b/services/core/java/com/android/server/statusbar/SessionMonitor.java
@@ -44,6 +44,7 @@
private final Context mContext;
private final Map<Integer, Set<ISessionListener>> mSessionToListeners =
new HashMap<>();
+ private final Map<Integer, Boolean> mSessionStatus = new HashMap<>();
/** */
public SessionMonitor(Context context) {
@@ -97,6 +98,8 @@
return;
}
+ mSessionStatus.put(sessionType, true);
+
synchronized (mSessionToListeners) {
for (ISessionListener listener : mSessionToListeners.get(sessionType)) {
try {
@@ -122,6 +125,8 @@
return;
}
+ mSessionStatus.put(sessionType, false);
+
synchronized (mSessionToListeners) {
for (ISessionListener listener : mSessionToListeners.get(sessionType)) {
try {
@@ -133,6 +138,13 @@
}
}
+ public boolean getSessionStatus(@SessionFlags int sessionType) {
+ if (mSessionStatus.containsKey(sessionType)) {
+ return mSessionStatus.get(sessionType);
+ }
+ return false;
+ }
+
private boolean isValidSessionType(@SessionFlags int sessionType) {
return ALL_SESSIONS.contains(sessionType);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 83cb72e..ef2158f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -139,7 +139,7 @@
*/
void setTopAppHidesStatusBar(int displayId, boolean hidesStatusBar);
- boolean showShutdownUi(boolean isReboot, String requestString);
+ boolean showShutdownUi(boolean isReboot, String requestString, boolean rebootCustom);
/**
* Notify system UI the immersive prompt should be dismissed as confirmed, and the confirmed
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index f8877ad..87e285c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -697,14 +697,14 @@
}
@Override
- public boolean showShutdownUi(boolean isReboot, String reason) {
+ public boolean showShutdownUi(boolean isReboot, String reason, boolean rebootCustom) {
if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) {
return false;
}
IStatusBar bar = mBar;
if (bar != null) {
try {
- bar.showShutdownUi(isReboot, reason);
+ bar.showShutdownUi(isReboot, reason, rebootCustom);
return true;
} catch (RemoteException ex) {}
}
@@ -1326,6 +1326,26 @@
return mTracingEnabled;
}
+ @Override
+ public void toggleCameraFlash() {
+ if (mBar != null) {
+ try {
+ mBar.toggleCameraFlash();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void toggleCameraFlashState(boolean enable) {
+ if (mBar != null) {
+ try {
+ mBar.toggleCameraFlashState(enable);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
// TODO(b/117478341): make it aware of multi-display if needed.
@Override
public void disable(int what, IBinder token, String pkg) {
@@ -1855,13 +1875,10 @@
* Allows the status bar to reboot the device.
*/
@Override
- public void reboot(boolean safeMode) {
+ public void reboot(boolean safeMode, String reason) {
enforceStatusBarService();
enforceValidCallingUser();
- String reason = safeMode
- ? PowerManager.REBOOT_SAFE_MODE
- : PowerManager.SHUTDOWN_USER_REQUESTED;
ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long identity = Binder.clearCallingIdentity();
try {
@@ -1871,7 +1888,7 @@
if (safeMode) {
ShutdownThread.rebootSafeMode(getUiContext(), true);
} else {
- ShutdownThread.reboot(getUiContext(), reason, false);
+ ShutdownThread.rebootCustom(getUiContext(), reason, false);
}
});
} finally {
@@ -2482,6 +2499,11 @@
mSessionMonitor.unregisterSessionListener(sessionFlags, listener);
}
+ @Override
+ public boolean getSessionStatus(@SessionFlags int sessionType) {
+ return mSessionMonitor.getSessionStatus(sessionType);
+ }
+
public String[] getStatusBarIcons() {
return mContext.getResources().getStringArray(R.array.config_statusBarIcons);
}
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 1798661..57f9f1f 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -47,6 +47,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -142,7 +143,9 @@
* */
@Override
public WebViewProviderInfo[] getWebViewPackages() {
- return mWebViewProviderPackages;
+ return Arrays.stream(mWebViewProviderPackages)
+ .filter(x -> isProviderAvailable(x.packageName))
+ .toArray(WebViewProviderInfo[]::new);
}
public long getFactoryPackageVersion(String packageName) throws NameNotFoundException {
@@ -151,6 +154,15 @@
.getLongVersionCode();
}
+ private boolean isProviderAvailable(String packageName) {
+ try {
+ getFactoryPackageVersion(packageName);
+ return true;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
/**
* Reads all signatures at the current depth (within the current provider) from the XML parser.
*/
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 258a87e..99d8ca4 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.content.ClipDescription.EXTRA_HIDE_DRAG_SOURCE_TASK_ID;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.View.DRAG_FLAG_GLOBAL;
import static android.view.View.DRAG_FLAG_GLOBAL_SAME_APPLICATION;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 866798d..ddbbfa9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3781,6 +3781,18 @@
confirm);
}
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public void reboot(String reason, boolean confirm) {
+ ShutdownThread.reboot(ActivityThread.currentActivityThread().getSystemUiContext(), reason, confirm);
+ }
+
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public void rebootCustom(String reason, boolean confirm) {
+ ShutdownThread.rebootCustom(ActivityThread.currentActivityThread().getSystemUiContext(), reason, confirm);
+ }
+
public void setCurrentUser(@UserIdInt int newUserId) {
synchronized (mGlobalLock) {
final TransitionController controller = mAtmService.getTransitionController();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 92dbf63..785ea98 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -310,6 +310,9 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
@@ -2932,6 +2935,26 @@
mSystemServiceManager.startService(TracingServiceProxy.class);
t.traceEnd();
+ // OmniRom Services
+ String externalServer = context.getResources().getString(
+ org.omnirom.omnilib.R.string.config_externalSystemServer);
+ final Class<?> serverClazz;
+ try {
+ serverClazz = Class.forName(externalServer);
+ final Constructor<?> constructor = serverClazz.getDeclaredConstructor(Context.class);
+ constructor.setAccessible(true);
+ final Object baseObject = constructor.newInstance(mSystemContext);
+ final Method method = baseObject.getClass().getDeclaredMethod("run");
+ method.setAccessible(true);
+ method.invoke(baseObject);
+ } catch (ClassNotFoundException
+ | IllegalAccessException
+ | InvocationTargetException
+ | InstantiationException
+ | NoSuchMethodException e) {
+ reportWtf("Making " + externalServer + " ready", e);
+ }
+
// UprobeStats DynamicInstrumentationManager
if (android.uprobestats.flags.Flags.executableMethodFileOffsets()) {
t.traceBegin("StartDynamicInstrumentationManager");
diff --git a/services/proguard.flags b/services/proguard.flags
index 0e1f68e..30c4525 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -128,3 +128,8 @@
# CoverageService guards optional jacoco class references with a runtime guard, so we can safely
# suppress build-time warnings.
-dontwarn org.jacoco.agent.rt.*
+
+# SDK
+-keep,allowoptimization,allowaccessmodification class omnirom.** { *; }
+-keep,allowoptimization,allowaccessmodification class org.omnirom.** { *; }
+-keep,allowoptimization,allowaccessmodification class vendor.lineage.** { *; }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 9fb7319..713f8a1 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2894,8 +2894,9 @@
for (size_t i = 0; i < basePackageCount; i++) {
size_t packageId = table.getBasePackageId(i);
String16 packageName(table.getBasePackageName(i));
- if (packageId > 0x01 && packageId != 0x7f &&
- packageName != String16("android")) {
+ if (packageId > 0x01 && packageId != 0x7f && packageId != 0x3f &&
+ packageName != String16("android") &&
+ packageName != String16("omnirom.platform")) {
libraryPackages.add(sp<Package>(new Package(packageName, packageId)));
}
}
diff --git a/tools/aapt2/Configuration.proto b/tools/aapt2/Configuration.proto
index 4883844..a8111a2 100644
--- a/tools/aapt2/Configuration.proto
+++ b/tools/aapt2/Configuration.proto
@@ -213,4 +213,6 @@
//
string product = 25;
+
+ string stringified = 100;
}
diff --git a/tools/aapt2/cmd/Convert.h b/tools/aapt2/cmd/Convert.h
index 9452e58..b78029f 100644
--- a/tools/aapt2/cmd/Convert.h
+++ b/tools/aapt2/cmd/Convert.h
@@ -74,6 +74,8 @@
"Has no effect on APKs where resource names are kept.",
&table_flattener_options_.deduplicate_entry_values);
AddOptionalSwitch("-v", "Enables verbose logging", &verbose_);
+ AddOptionalSwitch("--for-adevtool", "This flag exists to prevent using adevtool with "
+ "upstream aapt2 which lacks the Configuration.proto customization.", &for_adevtool_);
}
int Action(const std::vector<std::string>& args) override;
@@ -91,6 +93,7 @@
bool force_sparse_encoding_ = false;
bool enable_compact_entries_ = false;
std::optional<std::string> resources_config_path_;
+ bool for_adevtool_ = false;
};
int Convert(IAaptContext* context, LoadedApk* input, IArchiveWriter* output_writer,
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index fcc77d5..12c59c1 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -63,6 +63,7 @@
}
void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config) {
+ out_pb_config->set_stringified(config.to_string());
out_pb_config->set_mcc(config.mcc);
out_pb_config->set_mnc(config.mnc);
out_pb_config->set_locale(config.GetBcp47LanguageTag());