diff options
204 files changed, 4844 insertions, 1904 deletions
diff --git a/Android.bp b/Android.bp index 81a1fac6346e..43446145bf9b 100755 --- a/Android.bp +++ b/Android.bp @@ -252,6 +252,7 @@ java_library { "com.android.sysprop.init", "com.android.sysprop.localization", "PlatformProperties", + "vendor.lineage.touch-V1.0-java", ], sdk_version: "core_platform", installable: false, diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java index caf7e7f4a4ed..7ec603de40fd 100644 --- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java @@ -73,6 +73,8 @@ public interface DeviceIdleInternal { boolean isAppOnWhitelist(int appid); + int[] getPowerSaveWhitelistSystemAppIds(); + int[] getPowerSaveWhitelistUserAppIds(); int[] getPowerSaveTempWhitelistAppIds(); diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java index e08200b055d8..d002d69c320c 100644 --- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java @@ -112,6 +112,12 @@ public class AppStateTrackerImpl implements AppStateTracker { final SparseBooleanArray mActiveUids = new SparseBooleanArray(); /** + * System exemption list in the device idle controller. + */ + @GuardedBy("mLock") + private int[] mPowerExemptSystemAppIds = new int[0]; + + /** * System except-idle + user exemption list in the device idle controller. */ @GuardedBy("mLock") @@ -1040,6 +1046,7 @@ public class AppStateTrackerImpl implements AppStateTracker { * Called by device idle controller to update the power save exemption lists. */ public void setPowerSaveExemptionListAppIds( + int[] powerSaveExemptionListSystemAppIdArray, int[] powerSaveExemptionListExceptIdleAppIdArray, int[] powerSaveExemptionListUserAppIdArray, int[] tempExemptionListAppIdArray) { @@ -1047,6 +1054,7 @@ public class AppStateTrackerImpl implements AppStateTracker { final int[] previousExemptionList = mPowerExemptAllAppIds; final int[] previousTempExemptionList = mTempExemptAppIds; + mPowerExemptSystemAppIds = powerSaveExemptionListSystemAppIdArray; mPowerExemptAllAppIds = powerSaveExemptionListExceptIdleAppIdArray; mTempExemptAppIds = tempExemptionListAppIdArray; mPowerExemptUserAppIds = powerSaveExemptionListUserAppIdArray; @@ -1265,6 +1273,18 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** + * @return whether or not a UID is in either the user defined power-save exemption list or the + system full exemption list (not including except-idle) + */ + public boolean isUidPowerSaveIdleExempt(int uid) { + final int appId = UserHandle.getAppId(uid); + synchronized (mLock) { + return ArrayUtils.contains(mPowerExemptUserAppIds, appId) + || ArrayUtils.contains(mPowerExemptSystemAppIds, appId); + } + } + + /** * @return whether a UID is in the temp power-save exemption list or not. * * Note clients normally shouldn't need to access it. It's only for dumpsys. @@ -1299,6 +1319,9 @@ public class AppStateTrackerImpl implements AppStateTracker { pw.print("Active uids: "); dumpUids(pw, mActiveUids); + pw.print("System exemption list appids: "); + pw.println(Arrays.toString(mPowerExemptSystemAppIds)); + pw.print("Except-idle + user exemption list appids: "); pw.println(Arrays.toString(mPowerExemptAllAppIds)); @@ -1374,6 +1397,10 @@ public class AppStateTrackerImpl implements AppStateTracker { } } + for (int appId : mPowerExemptSystemAppIds) { + proto.write(AppStateTrackerProto.POWER_SAVE_SYSTEM_EXEMPT_APP_IDS, appId); + } + for (int appId : mPowerExemptAllAppIds) { proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId); } diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 8316a2625ccd..57cc315ac79a 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -588,6 +588,12 @@ public class DeviceIdleController extends SystemService private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray(); /** + * Current system app IDs that are in the complete power save white list. This array can + * be shared with others because it will not be modified once set. + */ + private int[] mPowerSaveWhitelistSystemAppIdArray = new int[0]; + + /** * App IDs that have been white-listed to opt out of power save restrictions, except * for device idle modes. */ @@ -2293,6 +2299,11 @@ public class DeviceIdleController extends SystemService return DeviceIdleController.this.isAppOnWhitelistInternal(appid); } + @Override + public int[] getPowerSaveWhitelistSystemAppIds() { + return DeviceIdleController.this.getPowerSaveSystemWhitelistAppIds(); + } + /** * Returns the array of app ids whitelisted by user. Take care not to * modify this, as it is a reference to the original copy. But the reference @@ -2517,6 +2528,12 @@ public class DeviceIdleController extends SystemService } } + int[] getPowerSaveSystemWhitelistAppIds() { + synchronized (this) { + return mPowerSaveWhitelistSystemAppIdArray; + } + } + int[] getPowerSaveWhitelistUserAppIds() { synchronized (this) { return mPowerSaveWhitelistUserAppIdArray; @@ -2527,6 +2544,16 @@ public class DeviceIdleController extends SystemService return new File(Environment.getDataDirectory(), "system"); } + /** Returns the keys of a SparseBooleanArray, paying no attention to its values. */ + private static int[] keysToIntArray(final SparseBooleanArray sparseArray) { + final int size = sparseArray.size(); + final int[] array = new int[size]; + for (int i = 0; i < size; i++) { + array[i] = sparseArray.keyAt(i); + } + return array; + } + @Override public void onStart() { final PackageManager pm = getContext().getPackageManager(); @@ -2563,6 +2590,7 @@ public class DeviceIdleController extends SystemService } catch (PackageManager.NameNotFoundException e) { } } + mPowerSaveWhitelistSystemAppIdArray = keysToIntArray(mPowerSaveWhitelistSystemAppIds); mConstants = mInjector.getConstants(this); @@ -4457,6 +4485,7 @@ public class DeviceIdleController extends SystemService private void passWhiteListsToForceAppStandbyTrackerLocked() { mAppStateTracker.setPowerSaveExemptionListAppIds( + mPowerSaveWhitelistSystemAppIdArray, mPowerSaveWhitelistExceptIdleAppIdArray, mPowerSaveWhitelistUserAppIdArray, mTempWhitelistAppIdArray); diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index df1b66612ea2..b7f723eda9d5 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -2910,7 +2910,7 @@ public class AlarmManagerService extends SystemService { } else if (workSource == null && (UserHandle.isCore(callingUid) || UserHandle.isSameApp(callingUid, mSystemUiUid) || ((mAppStateTracker != null) - && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) { + && mAppStateTracker.isUidPowerSaveIdleExempt(callingUid)))) { flags |= FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED; flags &= ~(FLAG_ALLOW_WHILE_IDLE | FLAG_PRIORITIZE); } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java index d5c9ae615486..b91d8f2cac44 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java @@ -75,6 +75,7 @@ public final class DeviceIdleJobsController extends StateController { * True when in device idle mode, so we don't want to schedule any jobs. */ private boolean mDeviceIdleMode; + private int[] mPowerSaveWhitelistSystemAppIds; private int[] mDeviceIdleWhitelistAppIds; private int[] mPowerSaveTempWhitelistAppIds; @@ -134,6 +135,8 @@ public final class DeviceIdleJobsController extends StateController { mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds(); + mPowerSaveWhitelistSystemAppIds = + mLocalDeviceIdleController.getPowerSaveWhitelistSystemAppIds(); mPowerSaveTempWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds(); mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor(); @@ -197,8 +200,9 @@ public final class DeviceIdleJobsController extends StateController { * Checks if the given job's scheduling app id exists in the device idle user whitelist. */ boolean isWhitelistedLocked(JobStatus job) { - return Arrays.binarySearch(mDeviceIdleWhitelistAppIds, - UserHandle.getAppId(job.getSourceUid())) >= 0; + final int appId = UserHandle.getAppId(job.getSourceUid()); + return Arrays.binarySearch(mDeviceIdleWhitelistAppIds, appId) >= 0 + || Arrays.binarySearch(mPowerSaveWhitelistSystemAppIds, appId) >= 0; } /** diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 385fd509757b..c825038c491d 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -239,6 +239,8 @@ public class StatusBarManager { public static final int CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER = 2; /** @hide */ public static final int CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE = 3; + /** @hide */ + public static final int CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE = 4; /** * Session flag for {@link #registerSessionListener} indicating the listener diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 002218a7cc0a..31e920c60b41 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -221,7 +221,6 @@ import android.telephony.MmsManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.TelephonyRegistryManager; import android.transparency.BinaryTransparencyManager; -import android.util.ArrayMap; import android.util.Log; import android.util.Slog; import android.uwb.UwbFrameworkInitializer; @@ -256,6 +255,7 @@ import com.android.internal.os.IDropBoxManagerService; import com.android.internal.policy.PhoneLayoutInflater; import com.android.internal.util.Preconditions; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -275,10 +275,10 @@ public final class SystemServiceRegistry { // Service registry information. // This information is never changed once static initialization has completed. private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES = - new ArrayMap<Class<?>, String>(); + new HashMap<Class<?>, String>(); private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = - new ArrayMap<String, ServiceFetcher<?>>(); - private static final Map<String, String> SYSTEM_SERVICE_CLASS_NAMES = new ArrayMap<>(); + new HashMap<String, ServiceFetcher<?>>(); + private static final Map<String, String> SYSTEM_SERVICE_CLASS_NAMES = new HashMap<>(); private static int sServiceCacheSize; diff --git a/core/java/android/app/admin/SystemUpdateInfo.java b/core/java/android/app/admin/SystemUpdateInfo.java index 9e6c91f4ec31..7459b0e05e3a 100644 --- a/core/java/android/app/admin/SystemUpdateInfo.java +++ b/core/java/android/app/admin/SystemUpdateInfo.java @@ -133,7 +133,7 @@ public final class SystemUpdateInfo implements Parcelable { 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 , Build.VERSION.INCREMENTAL); out.endTag(null, tag); } @@ -142,7 +142,7 @@ public final class SystemUpdateInfo implements Parcelable { 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 (!Build.VERSION.INCREMENTAL.equals(buildFingerprint)) { return null; } try { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 581ec8fb582f..18bbcc24abc3 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5279,6 +5279,15 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_SHOW_FOREGROUND_SERVICE_MANAGER = "android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER"; + /** + * Broadcast action: notify the system that the user has performed a gesture on the screen + * to launch the camera. Broadcast should be protected to receivers holding the + * {@link Manifest.permission#STATUS_BAR_SERVICE} permission. + * @hide + */ + public static final String ACTION_SCREEN_CAMERA_GESTURE = + "android.intent.action.SCREEN_CAMERA_GESTURE"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java index ff80e614be58..da3b68ecf789 100644 --- a/core/java/android/content/pm/PackagePartitions.java +++ b/core/java/android/content/pm/PackagePartitions.java @@ -131,7 +131,7 @@ public class PackagePartitions { 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.version.incremental"; return SystemProperties.digestOf(digestProperties); } diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java index 690dfcf9619b..c3d7cd56bed3 100644 --- a/core/java/android/content/res/ThemedResourceCache.java +++ b/core/java/android/content/res/ThemedResourceCache.java @@ -22,10 +22,10 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.Theme; import android.content.res.Resources.ThemeKey; -import android.util.ArrayMap; import android.util.LongSparseArray; import java.lang.ref.WeakReference; +import java.util.HashMap; /** * Data structure used for caching data against themes. @@ -35,7 +35,7 @@ import java.lang.ref.WeakReference; abstract class ThemedResourceCache<T> { public static final int UNDEFINED_GENERATION = -1; @UnsupportedAppUsage - private ArrayMap<ThemeKey, LongSparseArray<WeakReference<T>>> mThemedEntries; + private HashMap<ThemeKey, LongSparseArray<WeakReference<T>>> mThemedEntries; private LongSparseArray<WeakReference<T>> mUnthemedEntries; private LongSparseArray<WeakReference<T>> mNullThemedEntries; @@ -174,7 +174,7 @@ abstract class ThemedResourceCache<T> { if (mThemedEntries == null) { if (create) { - mThemedEntries = new ArrayMap<>(1); + mThemedEntries = new HashMap<>(1); } else { return null; } @@ -218,11 +218,8 @@ abstract class ThemedResourceCache<T> { */ private boolean pruneLocked(@Config int configChanges) { if (mThemedEntries != null) { - for (int i = mThemedEntries.size() - 1; i >= 0; i--) { - if (pruneEntriesLocked(mThemedEntries.valueAt(i), configChanges)) { - mThemedEntries.removeAt(i); - } - } + mThemedEntries.entrySet() + .removeIf(entry -> pruneEntriesLocked(entry.getValue(), configChanges)); } pruneEntriesLocked(mNullThemedEntries, configChanges); diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 6bc0f6ea947c..4c4952f2b775 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -175,6 +175,13 @@ public class BatteryManager { @SystemApi public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP"; + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * boolean value to indicate OEM fast charging + * {@hide} + */ + public static final String EXTRA_OEM_FAST_CHARGER = "oem_fast_charger"; + // values for "status" field in the ACTION_BATTERY_CHANGED Intent public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN; public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING; diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index 0d0d1da2fb7d..f2de5ffef283 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -162,6 +162,10 @@ public final class Trace { @UnsupportedAppUsage @SystemApi(client = MODULE_LIBRARIES) public static boolean isTagEnabled(long traceTag) { + if (!Build.IS_DEBUGGABLE) { + return false; + } + long tags = nativeGetEnabledTags(); return (tags & traceTag) != 0; } diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java index b7e3068a437c..16bb78e345ba 100644 --- a/core/java/android/os/UpdateEngine.java +++ b/core/java/android/os/UpdateEngine.java @@ -462,6 +462,17 @@ public class UpdateEngine { } /** + * @hide + */ + public void setPerformanceMode(boolean enable) { + try { + mUpdateEngine.setPerformanceMode(enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Unbinds the last bound callback function. */ public boolean unbind() { diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index b0dda6f6ced2..597ff73071b9 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -229,6 +229,9 @@ public final class PermissionManager { private List<SplitPermissionInfo> mSplitPermissionInfos; + private static String[] sLocationProviderPkgNames; + private static String[] sLocationExtraPkgNames; + /** * Creates a new instance. * @@ -1177,6 +1180,16 @@ public final class PermissionManager { 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; } @@ -1192,6 +1205,10 @@ public final class PermissionManager { 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/provider/Settings.java b/core/java/android/provider/Settings.java index 8378a37ec44a..fcfbcd54d2c8 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5758,6 +5758,12 @@ public final class Settings { "screen_flash_notification_color_global"; /** + * Whether or not to vibrate when a touchscreen gesture is detected + * @hide + */ + public static final String TOUCHSCREEN_GESTURE_HAPTIC_FEEDBACK = "touchscreen_gesture_haptic_feedback"; + + /** * IMPORTANT: If you add a new public settings you also have to add it to * PUBLIC_SETTINGS below. If the new setting is hidden you have to add * it to PRIVATE_SETTINGS below. Also add a validator that can validate @@ -11645,6 +11651,18 @@ public final class Settings { public static final String LOCK_SCREEN_WEATHER_ENABLED = "lockscreen_weather_enabled"; /** + * Controls whether double tap to sleep is enabled. + * @hide + */ + public static final String DOUBLE_TAP_SLEEP_GESTURE = "double_tap_sleep_gesture"; + + /** + * Whether to show swipe up hint in gestural nav mode + * @hide + */ + public static final String NAVIGATION_BAR_HINT = "navigation_bar_hint"; + + /** * These entries are considered common between the personal and the managed profile, * since the managed profile doesn't get to change them. */ diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java index d1d7c968411f..aecbe096cc48 100644 --- a/core/java/android/text/method/MetaKeyKeyListener.java +++ b/core/java/android/text/method/MetaKeyKeyListener.java @@ -348,8 +348,6 @@ public abstract class MetaKeyKeyListener { if (state == PRESSED) ; // repeat before use - else if (state == RELEASED) - content.setSpan(what, 0, 0, LOCKED); else if (state == USED) ; // repeat after use else if (state == LOCKED) diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java index d61228b295af..0ce0d4ba3dde 100644 --- a/core/java/android/text/style/TextAppearanceSpan.java +++ b/core/java/android/text/style/TextAppearanceSpan.java @@ -29,6 +29,8 @@ import android.text.ParcelableSpan; import android.text.TextPaint; import android.text.TextUtils; +import com.android.internal.graphics.fonts.DynamicMetrics; + /** * Sets the text appearance using the given * {@link android.R.styleable#TextAppearance TextAppearance} attributes. @@ -495,17 +497,17 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl styledTypeface = null; } + Typeface finalTypeface = null; if (styledTypeface != null) { - final Typeface readyTypeface; if (mTextFontWeight >= 0) { final int weight = Math.min(FontStyle.FONT_WEIGHT_MAX, mTextFontWeight); final boolean italic = (style & Typeface.ITALIC) != 0; - readyTypeface = ds.setTypeface(Typeface.create(styledTypeface, weight, italic)); + finalTypeface = ds.setTypeface(Typeface.create(styledTypeface, weight, italic)); } else { - readyTypeface = styledTypeface; + finalTypeface = styledTypeface; } - int fake = style & ~readyTypeface.getStyle(); + int fake = style & ~finalTypeface.getStyle(); if ((fake & Typeface.BOLD) != 0) { ds.setFakeBoldText(true); @@ -515,7 +517,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl ds.setTextSkewX(-0.25f); } - ds.setTypeface(readyTypeface); + ds.setTypeface(finalTypeface); } if (mTextSize > 0) { @@ -534,6 +536,12 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl ds.setLetterSpacing(mLetterSpacing); } + if ((!mHasLetterSpacing || mLetterSpacing == 0.0f) && + mTextSize > 0 && finalTypeface != null && + finalTypeface.getSystemFontFamilyName() != null) { + ds.setLetterSpacing(DynamicMetrics.calcTracking(mTextSize)); + } + if (mFontFeatureSettings != null) { ds.setFontFeatureSettings(mFontFeatureSettings); } diff --git a/core/java/android/util/BoostFramework.java b/core/java/android/util/BoostFramework.java index adcbeb855062..fea63951029f 100644 --- a/core/java/android/util/BoostFramework.java +++ b/core/java/android/util/BoostFramework.java @@ -30,6 +30,7 @@ package android.util; import android.content.Context; +import android.content.res.Resources; import android.graphics.BLASTBufferQueue; import android.os.SystemProperties; import android.util.Log; @@ -80,6 +81,9 @@ public class BoostFramework { private static Class<?> sUxPerfClass = null; private static Method sUxIOPStart = null; + private static final boolean sIsSupported = Resources.getSystem().getBoolean( + com.android.internal.R.bool.config_supportsBoostFramework); + /** @hide */ private Object mPerf = null; private Object mUxPerf = null; @@ -246,7 +250,7 @@ public class BoostFramework { private void initFunctions () { synchronized(BoostFramework.class) { - if (sIsLoaded == false) { + if (sIsSupported && sIsLoaded == false) { try { sPerfClass = Class.forName(PERFORMANCE_CLASS); @@ -340,6 +344,9 @@ public class BoostFramework { /** @hide */ public int perfLockAcquire(int duration, int... list) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sAcquireFunc != null) { Object retVal = sAcquireFunc.invoke(mPerf, duration, list); @@ -354,6 +361,9 @@ public class BoostFramework { /** @hide */ public int perfLockRelease() { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sReleaseFunc != null) { Object retVal = sReleaseFunc.invoke(mPerf); @@ -368,6 +378,9 @@ public class BoostFramework { /** @hide */ public int perfLockReleaseHandler(int handle) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sReleaseHandlerFunc != null) { Object retVal = sReleaseHandlerFunc.invoke(mPerf, handle); @@ -392,6 +405,9 @@ public class BoostFramework { /** @hide */ public int perfHint(int hint, String userDataStr, int userData1, int userData2) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sPerfHintFunc != null) { Object retVal = sPerfHintFunc.invoke(mPerf, hint, userDataStr, userData1, userData2); @@ -420,6 +436,9 @@ public class BoostFramework { /** @hide */ public int perfGetFeedback(int req, String pkg_name) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sFeedbackFunc != null) { Object retVal = sFeedbackFunc.invoke(mPerf, req, pkg_name); @@ -434,6 +453,9 @@ public class BoostFramework { /** @hide */ public int perfGetFeedbackExtn(int req, String pkg_name, int numArgs, int... list) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sFeedbackFuncExtn != null) { Object retVal = sFeedbackFuncExtn.invoke(mPerf, req, pkg_name, numArgs, list); @@ -448,6 +470,9 @@ public class BoostFramework { /** @hide */ public int perfIOPrefetchStart(int pid, String pkgName, String codePath) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { Object retVal = sIOPStart.invoke(mPerf, pid, pkgName, codePath); ret = (int) retVal; @@ -467,6 +492,9 @@ public class BoostFramework { /** @hide */ public int perfIOPrefetchStop() { int ret = -1; + if (!sIsSupported) { + return ret; + } try { Object retVal = sIOPStop.invoke(mPerf); ret = (int) retVal; @@ -484,6 +512,9 @@ public class BoostFramework { /** @hide */ public int perfUXEngine_events(int opcode, int pid, String pkgName, int lat, String codePath) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sUXEngineEvents == null) { return ret; @@ -501,6 +532,9 @@ public class BoostFramework { /** @hide */ public String perfUXEngine_trigger(int opcode) { String ret = null; + if (!sIsSupported) { + return ret; + } try { if (sUXEngineTrigger == null) { return ret; @@ -516,6 +550,9 @@ public class BoostFramework { /** @hide */ public String perfSyncRequest(int opcode) { String ret = null; + if (!sIsSupported) { + return ret; + } try { if (sPerfSyncRequest == null) { return ret; @@ -531,6 +568,9 @@ public class BoostFramework { /** @hide */ public String perfGetProp(String prop_name, String def_val) { String ret = ""; + if (!sIsSupported) { + return def_val; + } try { if (sPerfGetPropFunc != null) { Object retVal = sPerfGetPropFunc.invoke(mPerf, prop_name, def_val); @@ -547,6 +587,9 @@ public class BoostFramework { /** @hide */ public int perfLockAcqAndRelease(int handle, int duration, int numArgs,int reserveNumArgs, int... list) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sAcqAndReleaseFunc != null) { Object retVal = sAcqAndReleaseFunc.invoke(mPerf, handle, duration, numArgs, reserveNumArgs, list); @@ -565,6 +608,9 @@ public class BoostFramework { /** @hide */ public void perfEvent(int eventId, String pkg_name, int numArgs, int... list) { + if (!sIsSupported) { + return; + } try { if (sPerfEventFunc != null) { sPerfEventFunc.invoke(mPerf, eventId, pkg_name, numArgs, list); @@ -593,6 +639,9 @@ public class BoostFramework { public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, int hintType, int numArgs, int... list) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sperfHintAcqRelFunc != null) { Object retVal = sperfHintAcqRelFunc.invoke(mPerf,handle, hint, pkg_name, @@ -624,6 +673,9 @@ public class BoostFramework { public int perfHintRenew(int handle, int hint, String pkg_name, int duration, int hintType, int numArgs, int... list) { int ret = -1; + if (!sIsSupported) { + return ret; + } try { if (sperfHintRenewFunc != null) { Object retVal = sperfHintRenewFunc.invoke(mPerf,handle, hint, pkg_name, @@ -663,7 +715,7 @@ public class BoostFramework { private static Method sGetAdjustedAnimationClock = null; private static void initQXPerfFuncs() { - if (sQXIsLoaded) return; + if (!sIsSupported || sQXIsLoaded) return; try { sScrollOptProp = SystemProperties.getBoolean(SCROLL_OPT_PROP, false); @@ -718,6 +770,9 @@ public class BoostFramework { /** @hide */ public static void setFrameInterval(long frameIntervalNanos) { + if (!sIsSupported) { + return; + } if (sQXIsLoaded) { if (sScrollOptEnable && sSetFrameInterval != null) { try { @@ -750,6 +805,9 @@ public class BoostFramework { /** @hide */ public static void disableOptimizer(boolean disabled) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sDisableOptimizer != null) { try { sDisableOptimizer.invoke(null, disabled); @@ -761,6 +819,9 @@ public class BoostFramework { /** @hide */ public static void setBLASTBufferQueue(BLASTBufferQueue blastBufferQueue) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sSetBLASTBufferQueue != null) { try { sSetBLASTBufferQueue.invoke(null, blastBufferQueue); @@ -772,6 +833,9 @@ public class BoostFramework { /** @hide */ public static void setMotionType(int eventType) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sSetMotionType != null) { try { sSetMotionType.invoke(null, eventType); @@ -783,6 +847,9 @@ public class BoostFramework { /** @hide */ public static void setVsyncTime(long vsyncTimeNanos) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sSetVsyncTime != null) { try { sSetVsyncTime.invoke(null, vsyncTimeNanos); @@ -794,6 +861,9 @@ public class BoostFramework { /** @hide */ public static void setUITaskStatus(boolean running) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sSetUITaskStatus != null) { try { sSetUITaskStatus.invoke(null, running); @@ -805,6 +875,9 @@ public class BoostFramework { /** @hide */ public static void setFlingFlag(int flag) { + if (!sIsSupported) { + return; + } if (sScrollOptEnable && sSetFlingFlag != null) { try { sSetFlingFlag.invoke(null, flag); @@ -817,6 +890,9 @@ public class BoostFramework { /** @hide */ public static boolean shouldUseVsync(boolean defaultVsyncFlag) { boolean useVsync = defaultVsyncFlag; + if (!sIsSupported) { + return useVsync; + } if (sScrollOptEnable && sShouldUseVsync != null) { try { Object retVal = sShouldUseVsync.invoke(null); @@ -831,6 +907,9 @@ public class BoostFramework { /** @hide */ public static long getFrameDelay(long defaultDelay, long lastFrameTimeNanos) { long frameDelay = defaultDelay; + if (!sIsSupported) { + return frameDelay; + } if (sScrollOptEnable && sGetFrameDelay != null) { try { Object retVal = sGetFrameDelay.invoke(null, lastFrameTimeNanos); @@ -845,6 +924,9 @@ public class BoostFramework { /** @hide */ public static long getAdjustedAnimationClock(long frameTimeNanos) { long newFrameTimeNanos = frameTimeNanos; + if (!sIsSupported) { + return newFrameTimeNanos; + } if (sScrollOptEnable && sGetAdjustedAnimationClock != null) { try { Object retVal = sGetAdjustedAnimationClock.invoke(null, diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index 99a7fe598936..c4c5ebe1e7a2 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -812,67 +812,75 @@ public abstract class LayoutInflater { throws ClassNotFoundException, InflateException { Objects.requireNonNull(viewContext); Objects.requireNonNull(name); - Constructor<? extends View> constructor = sConstructorMap.get(name); - if (constructor != null && !verifyClassLoader(constructor)) { - constructor = null; - sConstructorMap.remove(name); - } + String prefixedName = prefix != null ? (prefix + name) : name; Class<? extends View> clazz = null; try { Trace.traceBegin(Trace.TRACE_TAG_VIEW, name); - if (constructor == null) { - // Class not found in the cache, see if it's real, and try to add it - clazz = Class.forName(prefix != null ? (prefix + name) : name, false, - mContext.getClassLoader()).asSubclass(View.class); - - if (mFilter != null && clazz != null) { - boolean allowed = mFilter.onLoadClass(clazz); - if (!allowed) { - failNotAllowed(name, prefix, viewContext, attrs); - } + // Opportunistically create view directly instead of using reflection + View view = tryCreateViewDirect(prefixedName, viewContext, attrs); + if (view == null) { + Constructor<? extends View> constructor = sConstructorMap.get(name); + if (constructor != null && !verifyClassLoader(constructor)) { + constructor = null; + sConstructorMap.remove(name); } - constructor = clazz.getConstructor(mConstructorSignature); - constructor.setAccessible(true); - sConstructorMap.put(name, constructor); - } else { - // If we have a filter, apply it to cached constructor - if (mFilter != null) { - // Have we seen this name before? - Boolean allowedState = mFilterMap.get(name); - if (allowedState == null) { - // New class -- remember whether it is allowed - clazz = Class.forName(prefix != null ? (prefix + name) : name, false, - mContext.getClassLoader()).asSubclass(View.class); - - boolean allowed = clazz != null && mFilter.onLoadClass(clazz); - mFilterMap.put(name, allowed); + + if (constructor == null) { + // Class not found in the cache, see if it's real, and try to add it + clazz = Class.forName(prefixedName, false, + mContext.getClassLoader()).asSubclass(View.class); + + if (mFilter != null && clazz != null) { + boolean allowed = mFilter.onLoadClass(clazz); if (!allowed) { failNotAllowed(name, prefix, viewContext, attrs); } - } else if (allowedState.equals(Boolean.FALSE)) { - failNotAllowed(name, prefix, viewContext, attrs); + } + constructor = clazz.getConstructor(mConstructorSignature); + constructor.setAccessible(true); + sConstructorMap.put(name, constructor); + } else { + // If we have a filter, apply it to cached constructor + if (mFilter != null) { + // Have we seen this name before? + Boolean allowedState = mFilterMap.get(name); + if (allowedState == null) { + // New class -- remember whether it is allowed + clazz = Class.forName(prefixedName, false, + mContext.getClassLoader()).asSubclass(View.class); + + boolean allowed = clazz != null && mFilter.onLoadClass(clazz); + mFilterMap.put(name, allowed); + if (!allowed) { + failNotAllowed(name, prefix, viewContext, attrs); + } + } else if (allowedState.equals(Boolean.FALSE)) { + failNotAllowed(name, prefix, viewContext, attrs); + } } } - } - Object lastContext = mConstructorArgs[0]; - mConstructorArgs[0] = viewContext; - Object[] args = mConstructorArgs; - args[1] = attrs; + Object lastContext = mConstructorArgs[0]; + mConstructorArgs[0] = viewContext; + Object[] args = mConstructorArgs; + args[1] = attrs; - try { - final View view = constructor.newInstance(args); - if (view instanceof ViewStub) { - // Use the same context when inflating ViewStub later. - final ViewStub viewStub = (ViewStub) view; - viewStub.setLayoutInflater(cloneInContext((Context) args[0])); + try { + view = constructor.newInstance(args); + } finally { + mConstructorArgs[0] = lastContext; } - return view; - } finally { - mConstructorArgs[0] = lastContext; } + + if (view instanceof ViewStub) { + // Use the same context when inflating ViewStub later. + final ViewStub viewStub = (ViewStub) view; + viewStub.setLayoutInflater(cloneInContext((Context) viewContext)); + } + + return view; } catch (NoSuchMethodException e) { final InflateException ie = new InflateException( getParserStateDescription(viewContext, attrs) @@ -1371,4 +1379,121 @@ public abstract class LayoutInflater { } } } + + // Some of the views included here are deprecated, but apps still use them. + @SuppressWarnings("deprecation") + private static View tryCreateViewDirect(String name, Context context, AttributeSet attributeSet) { + // This contains all the framework views used in a set of 113 real-world apps, sorted by + // number of occurrences. While views with only 1 occurrence are unlikely to be worth + // optimizing, it doesn't hurt to include them because switch-case is compiled into a table + // lookup after calling String#hashCode(). + switch (name) { + case "android.widget.LinearLayout": // 13486 occurrences + return new android.widget.LinearLayout(context, attributeSet); + case "android.widget.View": // 6930 occurrences + case "android.webkit.View": // 63 occurrences + case "android.view.View": // 63 occurrences + case "android.app.View": // 62 occurrences + return new android.view.View(context, attributeSet); + case "android.widget.FrameLayout": // 6447 occurrences + return new android.widget.FrameLayout(context, attributeSet); + case "android.widget.ViewStub": // 5613 occurrences + case "android.view.ViewStub": // 228 occurrences + case "android.app.ViewStub": // 227 occurrences + case "android.webkit.ViewStub": // 226 occurrences + return new android.view.ViewStub(context, attributeSet); + case "android.widget.TextView": // 4722 occurrences + return new android.widget.TextView(context, attributeSet); + case "android.widget.ImageView": // 3044 occurrences + return new android.widget.ImageView(context, attributeSet); + case "android.widget.RelativeLayout": // 2665 occurrences + return new android.widget.RelativeLayout(context, attributeSet); + case "android.widget.Space": // 1694 occurrences + return new android.widget.Space(context, attributeSet); + case "android.widget.ProgressBar": // 770 occurrences + return new android.widget.ProgressBar(context, attributeSet); + case "android.widget.Button": // 382 occurrences + return new android.widget.Button(context, attributeSet); + case "android.widget.ImageButton": // 265 occurrences + return new android.widget.ImageButton(context, attributeSet); + case "android.widget.Switch": // 145 occurrences + return new android.widget.Switch(context, attributeSet); + case "android.widget.DateTimeView": // 117 occurrences + return new android.widget.DateTimeView(context, attributeSet); + case "android.widget.Toolbar": // 86 occurrences + return new android.widget.Toolbar(context, attributeSet); + case "android.widget.HorizontalScrollView": // 68 occurrences + return new android.widget.HorizontalScrollView(context, attributeSet); + case "android.widget.ScrollView": // 67 occurrences + return new android.widget.ScrollView(context, attributeSet); + case "android.widget.NotificationHeaderView": // 65 occurrences + case "android.webkit.NotificationHeaderView": // 65 occurrences + case "android.view.NotificationHeaderView": // 65 occurrences + case "android.app.NotificationHeaderView": // 65 occurrences + return new android.view.NotificationHeaderView(context, attributeSet); + case "android.widget.ListView": // 58 occurrences + return new android.widget.ListView(context, attributeSet); + case "android.widget.QuickContactBadge": // 50 occurrences + return new android.widget.QuickContactBadge(context, attributeSet); + case "android.widget.SeekBar": // 40 occurrences + return new android.widget.SeekBar(context, attributeSet); + case "android.widget.CheckBox": // 38 occurrences + return new android.widget.CheckBox(context, attributeSet); + case "android.widget.GridLayout": // 16 occurrences + return new android.widget.GridLayout(context, attributeSet); + case "android.widget.TableRow": // 15 occurrences + return new android.widget.TableRow(context, attributeSet); + case "android.widget.RadioGroup": // 15 occurrences + return new android.widget.RadioGroup(context, attributeSet); + case "android.widget.Chronometer": // 15 occurrences + return new android.widget.Chronometer(context, attributeSet); + case "android.widget.ViewFlipper": // 13 occurrences + return new android.widget.ViewFlipper(context, attributeSet); + case "android.widget.Spinner": // 9 occurrences + return new android.widget.Spinner(context, attributeSet); + case "android.widget.ViewSwitcher": // 8 occurrences + return new android.widget.ViewSwitcher(context, attributeSet); + case "android.widget.TextSwitcher": // 8 occurrences + return new android.widget.TextSwitcher(context, attributeSet); + case "android.widget.SurfaceView": // 8 occurrences + case "android.webkit.SurfaceView": // 1 occurrence + case "android.view.SurfaceView": // 1 occurrence + case "android.app.SurfaceView": // 1 occurrence + return new android.view.SurfaceView(context, attributeSet); + case "android.widget.CheckedTextView": // 8 occurrences + return new android.widget.CheckedTextView(context, attributeSet); + case "android.preference.PreferenceFrameLayout": // 8 occurrences + return new android.preference.PreferenceFrameLayout(context, attributeSet); + case "android.widget.TwoLineListItem": // 7 occurrences + return new android.widget.TwoLineListItem(context, attributeSet); + case "android.widget.TableLayout": // 5 occurrences + return new android.widget.TableLayout(context, attributeSet); + case "android.widget.EditText": // 5 occurrences + return new android.widget.EditText(context, attributeSet); + case "android.widget.TabWidget": // 3 occurrences + return new android.widget.TabWidget(context, attributeSet); + case "android.widget.TabHost": // 3 occurrences + return new android.widget.TabHost(context, attributeSet); + case "android.widget.ZoomButton": // 2 occurrences + return new android.widget.ZoomButton(context, attributeSet); + case "android.widget.TextureView": // 2 occurrences + case "android.webkit.TextureView": // 2 occurrences + case "android.app.TextureView": // 2 occurrences + case "android.view.TextureView": // 2 occurrences + return new android.view.TextureView(context, attributeSet); + case "android.widget.ExpandableListView": // 2 occurrences + return new android.widget.ExpandableListView(context, attributeSet); + case "android.widget.ViewAnimator": // 1 occurrence + return new android.widget.ViewAnimator(context, attributeSet); + case "android.widget.TextClock": // 1 occurrence + return new android.widget.TextClock(context, attributeSet); + case "android.widget.AutoCompleteTextView": // 1 occurrence + return new android.widget.AutoCompleteTextView(context, attributeSet); + case "android.widget.WebView": // 1 occurrence + case "android.webkit.WebView": // 1 occurrence + return new android.webkit.WebView(context, attributeSet); + } + + return null; + } } diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 739c1bfccd3b..cbb3a3c28fba 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -316,7 +316,7 @@ public final class AutofillManager { /** @hide */ public static final int RECEIVER_FLAG_SESSION_FOR_AUGMENTED_AUTOFILL_ONLY = 0x1; /** @hide */ - public static final int DEFAULT_LOGGING_LEVEL = Build.IS_DEBUGGABLE + public static final int DEFAULT_LOGGING_LEVEL = Build.IS_ENG ? AutofillManager.FLAG_ADD_CLIENT_DEBUG : AutofillManager.NO_LOGGING; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 07c6e7ff21ed..b6033887eb51 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -692,6 +692,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private int mMinimumVelocity; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124051740) private int mMaximumVelocity; + private int mDecacheThreshold; private float mVelocityScale = 1.0f; final boolean[] mIsScrap = new boolean[1]; @@ -1002,6 +1003,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mVerticalScrollFactor = configuration.getScaledVerticalScrollFactor(); mMinimumVelocity = configuration.getScaledMinimumFlingVelocity(); mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + mDecacheThreshold = mMaximumVelocity / 2; mOverscrollDistance = configuration.getScaledOverscrollDistance(); mOverflingDistance = configuration.getScaledOverflingDistance(); @@ -4917,7 +4919,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Keep the fling alive a little longer postDelayed(this, FLYWHEEL_TIMEOUT); } else { - endFling(); + endFling(false); // Don't disable the scrolling cache right after it was enabled mTouchMode = TOUCH_MODE_SCROLL; reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); } @@ -4937,6 +4939,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // Use AbsListView#fling(int) instead @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void start(int initialVelocity) { + if (Math.abs(initialVelocity) > mDecacheThreshold) { + // For long flings, scrolling cache causes stutter, so don't use it + clearScrollingCache(); + } + int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mScroller.setInterpolator(null); @@ -5017,6 +5024,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // To interrupt a fling early you should use smoothScrollBy(0,0) instead @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) void endFling() { + endFling(true); + } + + void endFling(boolean clearCache) { mTouchMode = TOUCH_MODE_REST; removeCallbacks(this); @@ -5025,7 +5036,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (!mSuppressIdleStateChangeCall) { reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); } - clearScrollingCache(); + if (clearCache) + clearScrollingCache(); mScroller.abortAnimation(); if (mFlingStrictSpan != null) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 414918e64c76..606382efb9c0 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -233,6 +233,7 @@ import android.widget.RemoteViews.RemoteView; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; +import com.android.internal.graphics.fonts.DynamicMetrics; import com.android.internal.inputmethod.EditableInputConnection; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -4407,6 +4408,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setLetterSpacing(attributes.mLetterSpacing); } + if ((!attributes.mHasLetterSpacing || attributes.mLetterSpacing == 0.0f) && + DynamicMetrics.shouldModifyFont(mTextPaint.getTypeface())) { + setLetterSpacing(DynamicMetrics.calcTracking(mTextPaint.getTextSize())); + } + if (attributes.mFontFeatureSettings != null) { setFontFeatureSettings(attributes.mFontFeatureSettings); } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 2b39bb4eb7a5..1001ba83be83 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1420,15 +1420,18 @@ public class ChooserActivity extends ResolverActivity implements final ViewGroup actionRow = (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row); + String action = targetIntent.getAction(); + //TODO: addActionButton(actionRow, createCopyButton()); if (shouldNearbyShareBeIncludedAsActionButton()) { addActionButton(actionRow, createNearbyButton(targetIntent)); } - addActionButton(actionRow, createEditButton(targetIntent)); + if (!Intent.ACTION_SEND_MULTIPLE.equals(action)) { + addActionButton(actionRow, createEditButton(targetIntent)); + } mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false); - String action = targetIntent.getAction(); if (Intent.ACTION_SEND.equals(action)) { Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class); if (!validForContentPreview(uri)) { diff --git a/core/java/com/android/internal/graphics/fonts/DynamicMetrics.java b/core/java/com/android/internal/graphics/fonts/DynamicMetrics.java new file mode 100644 index 000000000000..79dacabb16ad --- /dev/null +++ b/core/java/com/android/internal/graphics/fonts/DynamicMetrics.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 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. + */ + +package com.android.internal.graphics.fonts; + +import android.app.ActivityThread; +import android.content.ComponentCallbacks; +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Typeface; + +public class DynamicMetrics { + // https://rsms.me/inter/dynmetrics/ + private static final float A = -0.0223f; + private static final float B = 0.185f; + private static final float C = -0.1745f; + + private static float sDensity = 0.0f; + + // Precalculated tracking LUT up to 32 dp, in steps of 0.5 dp to minimize rounding errors. + // Sizes are close enough that we can cast them to ints for lookup. + // In most cases, we should never have to calculate tracking at runtime because of this. + private static final float[] TRACKING_LUT = { + /* 0.0dp */ 0.1627f, + /* 0.5dp */ 0.147242871675558f, + /* 1.0dp */ 0.1330772180324039f, + /* 1.5dp */ 0.12009513371985438f, + /* 2.0dp */ 0.10819772909994156f, + /* 2.5dp */ 0.09729437696617904f, + /* 3.0dp */ 0.08730202220051463f, + /* 3.5dp */ 0.0781445491098568f, + /* 4.0dp */ 0.06975220162292829f, + /* 4.5dp */ 0.062061051930857966f, + /* 5.0dp */ 0.055012513523938045f, + /* 5.5dp */ 0.04855289491515605f, + /* 6.0dp */ 0.04263299065103837f, + /* 6.5dp */ 0.03720770649437408f, + /* 7.0dp */ 0.032235715923688846f, + /* 7.5dp */ 0.027679145332890072f, + /* 8.0dp */ 0.02350328553312564f, + /* 8.5dp */ 0.019676327359252226f, + /* 9.0dp */ 0.016169119366923862f, + /* 9.5dp */ 0.012954945774584309f, + /* 10.0dp */ 0.010009322958860013f, + /* 10.5dp */ 0.007309812953179257f, + /* 11.0dp */ 0.004835852528962955f, + /* 11.5dp */ 0.002568596557431524f, + /* 12.0dp */ 0.0004907744588531701f, + /* 12.5dp */ -0.0014134413542490412f, + /* 13.0dp */ -0.0031585560420509667f, + /* 13.5dp */ -0.004757862828932768f, + /* 14.0dp */ -0.006223544263193034f, + /* 14.5dp */ -0.007566765016306747f, + /* 15.0dp */ -0.008797756928615424f, + /* 15.5dp */ -0.00992589694927596f, + /* 16.0dp */ -0.010959778564167369f, + /* 16.5dp */ -0.01190727725584982f, + /* 17.0dp */ -0.012775610494210232f, + /* 17.5dp */ -0.013571392714766779f, + /* 18.0dp */ -0.014300685703423587f, + /* 18.5dp */ -0.014969044771476151f, + /* 19.0dp */ -0.01558156107260065f, + /* 19.5dp */ -0.01614290038417221f, + /* 20.0dp */ -0.016657338648324763f, + /* 20.5dp */ -0.017128794543482675f, + /* 21.0dp */ -0.01756085933447426f, + /* 21.5dp */ -0.017956824228607303f, + /* 22.0dp */ -0.018319705446088512f, + /* 22.5dp */ -0.018652267195758174f, + /* 23.0dp */ -0.01895704273115516f, + /* 23.5dp */ -0.01923635364730468f, + /* 24.0dp */ -0.019492327565219923f, + /* 24.5dp */ -0.01972691433882746f, + /* 25.0dp */ -0.019941900907770843f, + /* 25.5dp */ -0.02013892490923212f, + /* 26.0dp */ -0.020319487152457818f, + /* 26.5dp */ -0.02048496305101277f, + /* 27.0dp */ -0.020636613099845737f, + /* 27.5dp */ -0.02077559247697482f, + /* 28.0dp */ -0.020902959842932358f, + /* 28.5dp */ -0.021019685404998267f, + /* 29.0dp */ -0.021126658307650148f, + /* 29.5dp */ -0.0212246934055262f, + /* 30.0dp */ -0.02131453747049323f, + /* 30.5dp */ -0.02139687488010142f, + /* 31.0dp */ -0.021472332830757092f, + /* 31.5dp */ -0.0215414861153242f, + /* 32.0dp */ -0.02160486150154747f, + }; + + private static final ComponentCallbacks callbacks = new ComponentCallbacks() { + @Override + public void onConfigurationChanged(Configuration newConfig) { + sDensity = getDensity(); + } + + @Override + public void onLowMemory() {} + }; + + private DynamicMetrics() {} + + public static float calcTracking(float sizePx) { + if (sDensity == 0.0f) { + Context context = ActivityThread.currentApplication(); + if (context == null) { + return 0.0f; + } + + sDensity = getDensity(); + context.registerComponentCallbacks(callbacks); + } + + // Pixels -> sp + float sizeDp = sizePx / sDensity; + int lutIndex = (int) (sizeDp * 2); // 0.5dp steps + + // Precalculated lookup + if (lutIndex < TRACKING_LUT.length) { + return TRACKING_LUT[lutIndex]; + } + + return A + B * (float) Math.exp(C * sizeDp); + } + + public static boolean shouldModifyFont(Typeface typeface) { + return typeface == null || typeface.getSystemFontFamilyName() != null; + } + + private static float getDensity() { + Context context = ActivityThread.currentApplication(); + if (context == null) { + return 1.0f; + } + + return context.getResources().getDisplayMetrics().scaledDensity; + } +} diff --git a/core/java/com/android/internal/ice/hardware/HIDLHelper.java b/core/java/com/android/internal/ice/hardware/HIDLHelper.java new file mode 100644 index 000000000000..a596c0e5e3da --- /dev/null +++ b/core/java/com/android/internal/ice/hardware/HIDLHelper.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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.internal.ice.hardware; + +import android.util.Range; + +import java.util.ArrayList; + +class HIDLHelper { + + static TouchscreenGesture[] fromHIDLGestures( + ArrayList<vendor.lineage.touch.V1_0.Gesture> gestures) { + int size = gestures.size(); + TouchscreenGesture[] r = new TouchscreenGesture[size]; + for (int i = 0; i < size; i++) { + vendor.lineage.touch.V1_0.Gesture g = gestures.get(i); + r[i] = new TouchscreenGesture(g.id, g.name, g.keycode); + } + return r; + } + + static vendor.lineage.touch.V1_0.Gesture toHIDLGesture(TouchscreenGesture gesture) { + vendor.lineage.touch.V1_0.Gesture g = new vendor.lineage.touch.V1_0.Gesture(); + g.id = gesture.id; + g.name = gesture.name; + g.keycode = gesture.keycode; + return g; + } + +} diff --git a/core/java/com/android/internal/ice/hardware/LineageHardwareManager.java b/core/java/com/android/internal/ice/hardware/LineageHardwareManager.java new file mode 100644 index 000000000000..1c0797784183 --- /dev/null +++ b/core/java/com/android/internal/ice/hardware/LineageHardwareManager.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2015-2016 The CyanogenMod Project + * 2017-2019 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.internal.ice.hardware; + +import android.content.Context; +import android.hidl.base.V1_0.IBase; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Range; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; + +import com.android.internal.ice.hardware.HIDLHelper; + +import vendor.lineage.touch.V1_0.IGloveMode; +import vendor.lineage.touch.V1_0.IKeyDisabler; +import vendor.lineage.touch.V1_0.IStylusMode; +import vendor.lineage.touch.V1_0.ITouchscreenGesture; + +import java.io.UnsupportedEncodingException; +import java.lang.IllegalArgumentException; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * Manages access to LineageOS hardware extensions + * + * <p> + * This manager requires the HARDWARE_ABSTRACTION_ACCESS permission. + * <p> + * To get the instance of this class, utilize LineageHardwareManager#getInstance(Context context) + */ +public final class LineageHardwareManager { + private static final String TAG = "LineageHardwareManager"; + + // The VisibleForTesting annotation is to ensure Proguard doesn't remove these + // fields, as they might be used via reflection. When the @Keep annotation in + // the support library is properly handled in the platform, we should change this. + + /** + * High touch sensitivity for touch panels + */ + @VisibleForTesting + public static final int FEATURE_HIGH_TOUCH_SENSITIVITY = 0x10; + + /** + * Hardware navigation key disablement + */ + @VisibleForTesting + public static final int FEATURE_KEY_DISABLE = 0x20; + + /** + * Touchscreen hovering + */ + @VisibleForTesting + public static final int FEATURE_TOUCH_HOVERING = 0x800; + + /** + * Touchscreen gesture + */ + @VisibleForTesting + public static final int FEATURE_TOUCHSCREEN_GESTURES = 0x80000; + + private static final List<Integer> BOOLEAN_FEATURES = Arrays.asList( + FEATURE_HIGH_TOUCH_SENSITIVITY, + FEATURE_KEY_DISABLE, + FEATURE_TOUCH_HOVERING + ); + + private static LineageHardwareManager sLineageHardwareManagerInstance; + + private Context mContext; + + // HIDL hals + private HashMap<Integer, IBase> mHIDLMap = new HashMap<Integer, IBase>(); + + /** + * @hide to prevent subclassing from outside of the framework + */ + private LineageHardwareManager(Context context) { + Context appContext = context.getApplicationContext(); + if (appContext != null) { + mContext = appContext; + } else { + mContext = context; + } + } + + /** + * Determine if a Lineage Hardware feature is supported on this device + * + * @param feature The Lineage Hardware feature to query + * + * @return true if the feature is supported, false otherwise. + */ + public boolean isSupported(int feature) { + return isSupportedHIDL(feature); + } + + private boolean isSupportedHIDL(int feature) { + if (!mHIDLMap.containsKey(feature)) { + mHIDLMap.put(feature, getHIDLService(feature)); + } + return mHIDLMap.get(feature) != null; + } + + private IBase getHIDLService(int feature) { + try { + switch (feature) { + case FEATURE_HIGH_TOUCH_SENSITIVITY: + return IGloveMode.getService(true); + case FEATURE_KEY_DISABLE: + return IKeyDisabler.getService(true); + case FEATURE_TOUCH_HOVERING: + return IStylusMode.getService(true); + case FEATURE_TOUCHSCREEN_GESTURES: + return ITouchscreenGesture.getService(true); + } + } catch (NoSuchElementException | RemoteException e) { + } + return null; + } + + /** + * Get or create an instance of the {@link com.android.internal.custom.hardware.LineageHardwareManager} + * @param context + * @return {@link LineageHardwareManager} + */ + public static LineageHardwareManager getInstance(Context context) { + if (sLineageHardwareManagerInstance == null) { + sLineageHardwareManagerInstance = new LineageHardwareManager(context); + } + return sLineageHardwareManagerInstance; + } + + /** + * Determine if the given feature is enabled or disabled. + * + * Only used for features which have simple enable/disable controls. + * + * @param feature the Lineage Hardware feature to query + * + * @return true if the feature is enabled, false otherwise. + */ + public boolean get(int feature) { + if (!BOOLEAN_FEATURES.contains(feature)) { + throw new IllegalArgumentException(feature + " is not a boolean"); + } + + try { + if (isSupportedHIDL(feature)) { + IBase obj = mHIDLMap.get(feature); + switch (feature) { + case FEATURE_HIGH_TOUCH_SENSITIVITY: + IGloveMode gloveMode = (IGloveMode) obj; + return gloveMode.isEnabled(); + case FEATURE_KEY_DISABLE: + IKeyDisabler keyDisabler = (IKeyDisabler) obj; + return keyDisabler.isEnabled(); + case FEATURE_TOUCH_HOVERING: + IStylusMode stylusMode = (IStylusMode) obj; + return stylusMode.isEnabled(); + } + } + } catch (RemoteException e) { + } + return false; + } + + /** + * Enable or disable the given feature + * + * Only used for features which have simple enable/disable controls. + * + * @param feature the Lineage Hardware feature to set + * @param enable true to enable, false to disale + * + * @return true if the feature is enabled, false otherwise. + */ + public boolean set(int feature, boolean enable) { + if (!BOOLEAN_FEATURES.contains(feature)) { + throw new IllegalArgumentException(feature + " is not a boolean"); + } + + try { + if (isSupportedHIDL(feature)) { + IBase obj = mHIDLMap.get(feature); + switch (feature) { + case FEATURE_HIGH_TOUCH_SENSITIVITY: + IGloveMode gloveMode = (IGloveMode) obj; + return gloveMode.setEnabled(enable); + case FEATURE_KEY_DISABLE: + IKeyDisabler keyDisabler = (IKeyDisabler) obj; + return keyDisabler.setEnabled(enable); + case FEATURE_TOUCH_HOVERING: + IStylusMode stylusMode = (IStylusMode) obj; + return stylusMode.setEnabled(enable); + } + } + } catch (RemoteException e) { + } + return false; + } + + /** + * @return a list of available touchscreen gestures on the devices + */ + public TouchscreenGesture[] getTouchscreenGestures() { + try { + if (isSupportedHIDL(FEATURE_TOUCHSCREEN_GESTURES)) { + ITouchscreenGesture touchscreenGesture = (ITouchscreenGesture) + mHIDLMap.get(FEATURE_TOUCHSCREEN_GESTURES); + return HIDLHelper.fromHIDLGestures(touchscreenGesture.getSupportedGestures()); + } + } catch (RemoteException e) { + } + return null; + } + + /** + * @return true if setting the activation status was successful + */ + public boolean setTouchscreenGestureEnabled( + TouchscreenGesture gesture, boolean state) { + try { + if (isSupportedHIDL(FEATURE_TOUCHSCREEN_GESTURES)) { + ITouchscreenGesture touchscreenGesture = (ITouchscreenGesture) + mHIDLMap.get(FEATURE_TOUCHSCREEN_GESTURES); + return touchscreenGesture.setGestureEnabled( + HIDLHelper.toHIDLGesture(gesture), state); + } + } catch (RemoteException e) { + } + return false; + } +} diff --git a/core/java/com/android/internal/ice/hardware/TouchscreenGesture.aidl b/core/java/com/android/internal/ice/hardware/TouchscreenGesture.aidl new file mode 100644 index 000000000000..e922eee9a1b6 --- /dev/null +++ b/core/java/com/android/internal/ice/hardware/TouchscreenGesture.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * 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.internal.ice.hardware; + +parcelable TouchscreenGesture; diff --git a/core/java/com/android/internal/ice/hardware/TouchscreenGesture.java b/core/java/com/android/internal/ice/hardware/TouchscreenGesture.java new file mode 100644 index 000000000000..166dd3223d2c --- /dev/null +++ b/core/java/com/android/internal/ice/hardware/TouchscreenGesture.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * 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.internal.ice.hardware; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Touchscreen gestures API + * + * A device may implement several touchscreen gestures for use while + * the display is turned off, such as drawing alphabets and shapes. + * These gestures can be interpreted by userspace to activate certain + * actions and launch certain apps, such as to skip music tracks, + * to turn on the flashlight, or to launch the camera app. + * + * This *should always* be supported by the hardware directly. + * A lot of recent touch controllers have a firmware option for this. + * + * This API provides support for enumerating the gestures + * supported by the touchscreen. + * + * A TouchscreenGesture is referenced by it's identifier and carries an + * associated name (up to the user to translate this value). + */ +public class TouchscreenGesture implements Parcelable { + + public final int id; + public final String name; + public final int keycode; + + public TouchscreenGesture(int id, String name, int keycode) { + this.id = id; + this.name = name; + this.keycode = keycode; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(id); + parcel.writeString(name); + parcel.writeInt(keycode); + } + + /** @hide */ + public static final Parcelable.Creator<TouchscreenGesture> CREATOR = + new Parcelable.Creator<TouchscreenGesture>() { + + public TouchscreenGesture createFromParcel(Parcel in) { + return new TouchscreenGesture(in.readInt(), in.readString(), in.readInt()); + } + + @Override + public TouchscreenGesture[] newArray(int size) { + return new TouchscreenGesture[size]; + } + }; +} diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java index fef5e83cecca..901ecd202d6f 100644 --- a/core/java/com/android/internal/notification/SystemNotificationChannels.java +++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java @@ -105,7 +105,7 @@ public class SystemNotificationChannels { final NotificationChannel developerImportant = new NotificationChannel( DEVELOPER_IMPORTANT, context.getString(R.string.notification_channel_developer_important), - NotificationManager.IMPORTANCE_HIGH); + NotificationManager.IMPORTANCE_MIN); developer.setBlockable(true); channelsList.add(developerImportant); diff --git a/core/java/com/android/internal/os/DeviceKeyHandler.java b/core/java/com/android/internal/os/DeviceKeyHandler.java new file mode 100644 index 000000000000..8902337f3ebb --- /dev/null +++ b/core/java/com/android/internal/os/DeviceKeyHandler.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 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. + */ + +package com.android.internal.os; + +import android.view.KeyEvent; + +public interface DeviceKeyHandler { + + /** + * Invoked when an unknown key was detected by the system, letting the device handle + * this special keys prior to pass the key to the active app. + * + * @param event The key event to be handled + * @return null if event is consumed, KeyEvent to be handled otherwise + */ + public KeyEvent handleKeyEvent(KeyEvent event); +} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 807b96fb970e..327bd619ce25 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -119,7 +119,7 @@ public class LockPatternUtils { public static final int PIN_LENGTH_UNAVAILABLE = -1; // This is the minimum pin length at which auto confirmation is supported - public static final int MIN_AUTO_PIN_REQUIREMENT_LENGTH = 6; + public static final int MIN_AUTO_PIN_REQUIREMENT_LENGTH = 4; /** * Header used for the encryption and decryption of the device credential for diff --git a/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java index 9c632ea725a9..ca94bb08afc0 100644 --- a/core/java/com/android/server/LocalServices.java +++ b/core/java/com/android/server/LocalServices.java @@ -18,7 +18,7 @@ package com.android.server; import com.android.internal.annotations.VisibleForTesting; -import android.util.ArrayMap; +import java.util.HashMap; /** * This class is used in a similar way as ServiceManager, except the services registered here @@ -32,8 +32,8 @@ import android.util.ArrayMap; public final class LocalServices { private LocalServices() {} - private static final ArrayMap<Class<?>, Object> sLocalServiceObjects = - new ArrayMap<Class<?>, Object>(); + private static final HashMap<Class<?>, Object> sLocalServiceObjects = + new HashMap<Class<?>, Object>(); /** * Returns a local service instance that implements the specified interface. diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 4c90141afb76..9b56e6b869c9 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -652,10 +652,7 @@ static void PreApplicationInit() { void *mBelugaHandle = nullptr; void (*mBeluga)() = nullptr; mBelugaHandle = dlopen("libbeluga.so", RTLD_NOW); - if (!mBelugaHandle) { - ALOGW("Unable to open libbeluga.so: %s.", dlerror()); - } - else { + if (mBelugaHandle) { mBeluga = (void (*) ())dlsym(mBelugaHandle, "beluga"); if (mBeluga) mBeluga(); diff --git a/core/proto/android/server/appstatetracker.proto b/core/proto/android/server/appstatetracker.proto index f5583d4f476f..0d0fb097d963 100644 --- a/core/proto/android/server/appstatetracker.proto +++ b/core/proto/android/server/appstatetracker.proto @@ -25,7 +25,7 @@ option java_multiple_files = true; // Dump from com.android.server.AppStateTracker. // -// Next ID: 14 +// Next ID: 15 message AppStateTrackerProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; @@ -41,6 +41,9 @@ message AppStateTrackerProto { // UIDs currently in the foreground. repeated int32 foreground_uids = 11; + // App ids that are in power-save system exemption list. + repeated int32 power_save_system_exempt_app_ids = 14; + // App ids that are in power-save exemption list. repeated int32 power_save_exempt_app_ids = 3; diff --git a/core/res/res/drawable/toast_frame.xml b/core/res/res/drawable/toast_frame.xml index a8cdef6d05f1..34987394b2ec 100644 --- a/core/res/res/drawable/toast_frame.xml +++ b/core/res/res/drawable/toast_frame.xml @@ -17,7 +17,7 @@ --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <solid android:color="?android:attr/colorSurface" /> + <solid android:color="?android:attr/colorBackgroundFloating" /> <corners android:radius="28dp" /> </shape> diff --git a/core/res/res/drawable/toast_frame_legacy.xml b/core/res/res/drawable/toast_frame_legacy.xml new file mode 100644 index 000000000000..aee219afbb4a --- /dev/null +++ b/core/res/res/drawable/toast_frame_legacy.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* Copyright 2017, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="?android:attr/colorBackground" /> + <corners android:radius="28dp" /> +</shape> diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml index 8bedb897dc19..49c0a37370a8 100644 --- a/core/res/res/layout/transient_notification.xml +++ b/core/res/res/layout/transient_notification.xml @@ -25,7 +25,7 @@ android:orientation="horizontal" android:gravity="center_vertical" android:maxWidth="@dimen/toast_width" - android:background="?android:attr/colorBackground" + android:background="@drawable/toast_frame_legacy" android:elevation="@dimen/toast_elevation" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" diff --git a/core/res/res/layout/transient_notification_with_icon.xml b/core/res/res/layout/transient_notification_with_icon.xml index 0dfb3adc8364..142fa5ed5410 100644 --- a/core/res/res/layout/transient_notification_with_icon.xml +++ b/core/res/res/layout/transient_notification_with_icon.xml @@ -22,7 +22,7 @@ android:orientation="horizontal" android:gravity="center_vertical" android:maxWidth="@dimen/toast_width" - android:background="?android:attr/colorBackground" + android:background="@drawable/toast_frame_legacy" android:elevation="@dimen/toast_elevation" android:layout_marginEnd="16dp" android:layout_marginStart="16dp" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4b6eaa86c701..5dcfa8d5c00c 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -885,11 +885,11 @@ <integer name="config_defaultNightDisplayCustomEndTime">21600000</integer> <!-- Minimum color temperature, in Kelvin, supported by Night display. --> - <integer name="config_nightDisplayColorTemperatureMin">2596</integer> + <integer name="config_nightDisplayColorTemperatureMin">1600</integer> <!-- Default color temperature, in Kelvin, to tint the screen when Night display is activated. --> - <integer name="config_nightDisplayColorTemperatureDefault">2850</integer> + <integer name="config_nightDisplayColorTemperatureDefault">2650</integer> <!-- Maximum color temperature, in Kelvin, supported by Night display. --> <integer name="config_nightDisplayColorTemperatureMax">4082</integer> diff --git a/core/res/res/values/ice_config.xml b/core/res/res/values/ice_config.xml new file mode 100644 index 000000000000..265fbc248b0b --- /dev/null +++ b/core/res/res/values/ice_config.xml @@ -0,0 +1,54 @@ +<!-- + Copyright (C) 2022 Project ICE + + 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> + <!-- The list of components which should be automatically disabled for a specific device. + Note: this MUST not be used to randomly disable components, ask for approval first! --> + <string-array name="config_deviceDisabledComponents" translatable="false"> + </string-array> + + <!-- The list of components which should be automatically disabled for all devices. --> + <string-array name="config_globallyDisabledComponents" translatable="false"> + </string-array> + + <!-- The list of components which should be forced to be enabled. --> + <string-array name="config_forceEnabledComponents" translatable="false"> + </string-array> + + <!-- Paths to the libraries that contain device specific key handlers --> + <string-array name="config_deviceKeyHandlerLibs" translatable="false"> + </string-array> + + <!-- Names of the key handler classes --> + <string-array name="config_deviceKeyHandlerClasses" translatable="false"> + </string-array> + + <!-- Path to fast charging status file to detect whether an oem fast charger is active --> + <string name="config_oemFastChargerStatusPath" translatable="false"></string> + + <!-- Expected value from fast charging status file --> + <string name="config_oemFastChargerStatusValue" translatable="false">1</string> + + <!-- Whether device has an alert slider --> + <bool name="config_hasAlertSlider" translatable="false">false</bool> + + <!-- The location of the device's alert slider: + 0: Left side + 1: Right side --> + <integer name="config_alertSliderLocation">0</integer> + + <!-- Whether device supports QTI Boost Framework --> + <bool name="config_supportsBoostFramework">true</bool> +</resources> diff --git a/core/res/res/values/ice_symbols.xml b/core/res/res/values/ice_symbols.xml new file mode 100644 index 000000000000..dcc26d998032 --- /dev/null +++ b/core/res/res/values/ice_symbols.xml @@ -0,0 +1,38 @@ +<!-- + Copyright (C) 2022 Project ICE + + 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> + <!-- Package Manager --> + <java-symbol type="array" name="config_deviceDisabledComponents" /> + <java-symbol type="array" name="config_globallyDisabledComponents" /> + <java-symbol type="array" name="config_forceEnabledComponents" /> + + <!-- Device keyhandlers --> + <java-symbol type="array" name="config_deviceKeyHandlerLibs" /> + <java-symbol type="array" name="config_deviceKeyHandlerClasses" /> + + <!-- Path to fast charging status file to detect whether an oem fast charger is active --> + <java-symbol type="string" name="config_oemFastChargerStatusPath" /> + + <!-- Expected value from fast charging status file --> + <java-symbol type="string" name="config_oemFastChargerStatusValue" /> + + <!-- Alert Slider --> + <java-symbol type="bool" name="config_hasAlertSlider" /> + <java-symbol type="integer" name="config_alertSliderLocation" /> + + <!-- Boost Framework --> + <java-symbol type="bool" name="config_supportsBoostFramework" /> +</resources> diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp index f90a74d939f4..81716878df3a 100644 --- a/data/fonts/Android.bp +++ b/data/fonts/Android.bp @@ -30,16 +30,6 @@ license { } prebuilt_font { - name: "DroidSansMono.ttf", - src: "DroidSansMono.ttf", - required: [ - // Roboto-Regular.ttf provides DroidSans.ttf as a symlink to itself - // Roboto-Regular.ttf provides DroidSans-Bold.ttf as a symlink to itself - "Roboto-Regular.ttf", - ], -} - -prebuilt_font { name: "AndroidClock.ttf", src: "AndroidClock.ttf", } diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml index c9c1af8b807b..14f85c9e3dc6 100644 --- a/data/fonts/fonts.xml +++ b/data/fonts/fonts.xml @@ -25,88 +25,92 @@ <!-- first font is default --> <family name="sans-serif"> <font weight="100" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="100" /> </font> <font weight="200" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="200" /> </font> <font weight="300" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="300" /> </font> - <font weight="400" style="normal">RobotoStatic-Regular.ttf</font> + <font weight="400" style="normal">Roboto-Regular.ttf + <axis tag="slnt" stylevalue="0" /> + <axis tag="wdth" stylevalue="100" /> + <axis tag="wght" stylevalue="400" /> + </font> <font weight="500" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="500" /> </font> <font weight="600" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="600" /> </font> <font weight="700" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="700" /> </font> <font weight="800" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="800" /> </font> <font weight="900" style="normal">Roboto-Regular.ttf - <axis tag="ital" stylevalue="0" /> + <axis tag="slnt" stylevalue="0" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="900" /> </font> <font weight="100" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="100" /> </font> <font weight="200" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="200" /> </font> <font weight="300" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="300" /> </font> <font weight="400" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="400" /> </font> <font weight="500" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="500" /> </font> <font weight="600" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="600" /> </font> <font weight="700" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="700" /> </font> <font weight="800" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="800" /> </font> <font weight="900" style="italic">Roboto-Regular.ttf - <axis tag="ital" stylevalue="1" /> + <axis tag="slnt" stylevalue="-10" /> <axis tag="wdth" stylevalue="100" /> <axis tag="wght" stylevalue="900" /> </font> @@ -274,6 +278,98 @@ <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/> <!-- fallback fonts --> + <family> + <font weight="100" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="100"/> + </font> + <font weight="100" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="100"/> + </font> + <font weight="200" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="200"/> + </font> + <font weight="200" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="200"/> + </font> + <font weight="300" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="300"/> + </font> + <font weight="300" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="300"/> + </font> + <font weight="400" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="400"/> + </font> + <font weight="400" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="400"/> + </font> + <font weight="500" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="500"/> + </font> + <font weight="500" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="500"/> + </font> + <font weight="600" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="600"/> + </font> + <font weight="600" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="600"/> + </font> + <font weight="700" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="700"/> + </font> + <font weight="700" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="700"/> + </font> + <font weight="800" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="800"/> + </font> + <font weight="800" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="800"/> + </font> + <font weight="900" style="normal">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="0"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="900"/> + </font> + <font weight="900" style="italic">RobotoFallback-VF.ttf + <axis tag="ital" stylevalue="1"/> + <axis tag="wdth" stylevalue="100"/> + <axis tag="wght" stylevalue="900"/> + </font> + </family> <family lang="und-Arab" variant="elegant"> <font weight="400" style="normal" postScriptName="NotoNaskhArabic"> NotoNaskhArabic-Regular.ttf diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm index 1048742adb70..2691fd13dbd5 100644 --- a/data/keyboards/Generic.kcm +++ b/data/keyboards/Generic.kcm @@ -499,7 +499,7 @@ key PLUS { ### Non-printing keys ### key ESCAPE { - base: none + base: fallback BACK alt, meta: fallback HOME ctrl: fallback MENU } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index d35dcab11f49..e4e814a1c941 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -260,7 +260,7 @@ public class Paint { // These flags are always set on a new/reset paint, even if flags 0 is passed. static final int HIDDEN_DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG - | FILTER_BITMAP_FLAG; + | FILTER_BITMAP_FLAG | SUBPIXEL_TEXT_FLAG; /** * Font hinter option that disables font hinting. diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/styles.xml b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/styles.xml index d0b6c4d54bb1..737d6ac69d40 100644 --- a/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/styles.xml +++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/res/values-v31/styles.xml @@ -19,10 +19,12 @@ <item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item> <item name="android:textSize">20dp</item> <item name="android:textColor">@color/settingslib_text_color_primary_device_default</item> + <item name="android:letterSpacing">-0.016657338648324763</item> </style> <style name="CollapsingToolbarTitle.Expanded" parent="CollapsingToolbarTitle.Collapsed"> <item name="android:textSize">36dp</item> <item name="android:textColor">@color/settingslib_text_color_primary_device_default</item> + <item name="android:letterSpacing">-0.02195411335559237</item> </style> -</resources>
\ No newline at end of file +</resources> 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 a0ff216875a2..453810e2e3d3 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 @@ -88,6 +88,13 @@ class AppInfoProvider(private val packageInfo: PackageInfo) { } } + @Composable + fun FooterAppPackageName() { + Box(modifier = Modifier.padding(SettingsDimension.itemPadding)) { + SettingsBody(packageInfo.packageName) + } + } + private companion object { /** Wrapped the version name, so its directionality still keep same when RTL. */ val PackageInfo.versionNameBidiWrapped: String diff --git a/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml index 1d048ae44049..1272ea7a30e1 100644 --- a/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml @@ -14,20 +14,17 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="19.41dp" - android:height="15dp" - android:viewportWidth="22" - android:viewportHeight="17"> - - <path - android:fillColor="#FFFFFFFF" - android:pathData="M5.32,10.13h1.11v1.03H5.32v2.31H4.11v-2.31H0.35v-0.75l3.7-6.9h1.27V10.13z M1.69,10.13h2.42V5.4L1.69,10.13z" /> + android:width="27dp" + android:height="16dp" + android:viewportWidth="27.0" + android:viewportHeight="16.0"> <path - android:fillColor="#FFFFFFFF" - android:pathData="M14.15,12.24l-0.22,0.27c-0.63,0.73-1.55,1.1-2.76,1.1c-1.08,0-1.92-0.36-2.53-1.07c-0.61-0.71-0.93-1.72-0.94-3.02V7.56 c0-1.39,0.28-2.44,0.84-3.13s1.39-1.04,2.51-1.04c0.95,0,1.69,0.26,2.23,0.79s0.83,1.28,0.89,2.26H12.9 c-0.05-0.62-0.22-1.1-0.52-1.45s-0.74-0.52-1.34-0.52c-0.72,0-1.24,0.23-1.57,0.7S8.97,6.37,8.96,7.4v2.03 c0,1,0.19,1.77,0.57,2.31c0.38,0.54,0.93,0.8,1.65,0.8c0.67,0,1.19-0.16,1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z" /> + android:fillColor="#FF000000" + android:pathData="M2,10.98V9.81l4.28,-6.83h1.6v6.59h1.19v1.41H7.88V13H6.4v-2.02H2zM3.68,9.57H6.4V5.33H6.31L3.68,9.57z"/> <path - android:fillColor="#FFFFFFFF" - android:pathData="M 19.3 5.74 L 19.3 3.39 L 18 3.39 L 18 5.74 L 15.65 5.74 L 15.65 7.04 L 18 7.04 L 18 9.39 L 19.3 9.39 L 19.3 7.04 L 21.65 7.04 L 21.65 5.74 Z" /> + android:fillColor="#FF000000" + android:pathData="M15,13.22c-0.88,0 -1.66,-0.21 -2.34,-0.64c-0.67,-0.44 -1.2,-1.05 -1.6,-1.83c-0.38,-0.79 -0.57,-1.71 -0.57,-2.76c0,-1.05 0.21,-1.96 0.62,-2.74c0.41,-0.79 0.97,-1.4 1.67,-1.83c0.7,-0.44 1.5,-0.66 2.39,-0.66c1.09,0 2.01,0.25 2.74,0.76c0.75,0.5 1.22,1.21 1.41,2.11l-1.47,0.39c-0.17,-0.56 -0.48,-1 -0.94,-1.32c-0.45,-0.33 -1.03,-0.49 -1.75,-0.49c-0.57,0 -1.09,0.14 -1.57,0.43c-0.48,0.29 -0.85,0.71 -1.13,1.27c-0.28,0.56 -0.42,1.25 -0.42,2.07c0,0.81 0.14,1.5 0.41,2.07c0.28,0.56 0.65,0.98 1.11,1.27c0.47,0.29 0.98,0.43 1.54,0.43c0.57,0 1.06,-0.11 1.47,-0.34c0.42,-0.23 0.75,-0.55 0.99,-0.94c0.25,-0.4 0.41,-0.85 0.46,-1.36h-2.88V7.79h4.37c0,0.87 0,1.74 0,2.6c0,0.87 0,1.74 0,2.6h-1.41v-1.4h-0.08c-0.28,0.49 -0.67,0.88 -1.18,1.18C16.34,13.07 15.73,13.22 15,13.22z"/> <path - android:pathData="M 0 0 H 22 V 17 H 0 V 0 Z" /> + android:fillColor="#FF000000" + android:pathData="M24.62 5.24 24.62 2.89 23.32 2.89 23.32 5.24 20.97 5.24 20.97 6.54 23.32 6.54 23.32 8.89 24.62 8.89 24.62 6.54 26.97 6.54 26.97 5.24Z"/> </vector> diff --git a/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml index 10bbcc7b3737..60de42cfdc95 100644 --- a/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml @@ -1,5 +1,6 @@ <!-- Copyright (C) 2018 The Android Open Source Project + (C) 2023 Paranoid Android Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,20 +15,17 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:viewportWidth="22" - android:viewportHeight="17" - android:width="22dp" - android:height="17dp"> - <group> - <group> - <path android:fillColor="#FF000000" - android:pathData="M1.03 8.47l0.43-4.96h4.33v1.17H2.48L2.25 7.39C2.66 7.1 3.1 6.96 3.57 6.96c0.77 0 1.38 0.3 1.83 0.9 s0.66 1.41 0.66 2.43c0 1.03-0.24 1.84-0.72 2.43S4.2 13.6 3.36 13.6c-0.75 0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07 0.57 0.23 1 0.49 1.29s0.59 0.43 1.01 0.43c0.47 0 0.84-0.2 1.1-0.61c0.26-0.41 0.4-0.96 0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.76 8.09 3.28 8.09c-0.4 0-0.72 0.1-0.96 0.31L1.99 8.73L1.03 8.47z"/> - </group> - <group> - <path android:fillColor="#FF000000" - android:pathData="M 18.93,5.74 L 18.93,3.39 L 17.63,3.39 L 17.63,5.74 L 15.28,5.74 L 15.28,7.04 L 17.63,7.04 L 17.63,9.39 L 18.93,9.39 L 18.93,7.04 L 21.28,7.04 L 21.28,5.74 z"/> - </group> - <path android:fillColor="#FF000000" - android:pathData="M13.78 12.24l-0.22 0.27c-0.63 0.73-1.55 1.1-2.76 1.1c-1.08 0-1.92-0.36-2.53-1.07s-0.93-1.72-0.94-3.02V7.56 c0-1.39 0.28-2.44 0.84-3.13s1.39-1.04 2.51-1.04c0.95 0 1.69 0.26 2.23 0.79s0.83 1.28 0.89 2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45s-0.74-0.52-1.34-0.52c-0.72 0-1.24 0.23-1.57 0.7S8.6 6.37 8.59 7.4v2.03c0 1 0.19 1.77 0.57 2.31 c0.38 0.54 0.93 0.8 1.65 0.8c0.67 0 1.19-0.16 1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z"/> - </group> + android:width="27dp" + android:height="16dp" + android:viewportWidth="27" + android:viewportHeight="16"> + <path + android:pathData="M 5.3 13.22 C 4.73 13.22 4.2 13.11 3.72 12.88 C 3.24 12.66 2.85 12.33 2.54 11.9 C 2.24 11.47 2.06 10.93 2 10.3 L 3.48 10.1 C 3.55 10.6 3.73 11.02 4.04 11.35 C 4.36 11.67 4.78 11.83 5.3 11.83 C 5.87 11.83 6.32 11.65 6.64 11.28 C 6.97 10.91 7.13 10.41 7.13 9.8 C 7.13 9.19 6.97 8.71 6.64 8.34 C 6.32 7.96 5.88 7.78 5.32 7.78 C 5 7.78 4.7 7.85 4.42 8 C 4.15 8.14 3.93 8.33 3.76 8.56 L 2.28 7.92 L 2.88 2.98 L 8.14 2.98 L 8.14 4.34 L 4.1 4.34 L 3.72 7.02 L 3.8 7.05 C 4 6.87 4.25 6.73 4.55 6.62 C 4.85 6.5 5.18 6.44 5.56 6.44 C 6.16 6.44 6.69 6.58 7.16 6.85 C 7.62 7.11 7.98 7.5 8.24 8 C 8.51 8.5 8.65 9.1 8.65 9.79 C 8.65 10.45 8.51 11.05 8.22 11.57 C 7.94 12.08 7.55 12.49 7.04 12.79 C 6.55 13.08 5.97 13.22 5.3 13.22 Z" + android:fillColor="#FF000000"/> + <path + android:pathData="M 14.51 13.22 C 13.63 13.22 12.85 13.01 12.17 12.58 C 11.5 12.14 10.97 11.53 10.57 10.75 C 10.19 9.95 10 9.03 10 7.99 C 10 6.94 10.21 6.03 10.62 5.25 C 11.03 4.46 11.59 3.85 12.29 3.42 C 12.99 2.98 13.79 2.76 14.68 2.76 C 15.77 2.76 16.69 3.01 17.42 3.52 C 18.17 4.02 18.64 4.73 18.83 5.63 L 17.36 6.02 C 17.19 5.46 16.88 5.02 16.42 4.7 C 15.97 4.37 15.39 4.21 14.67 4.21 C 14.1 4.21 13.58 4.35 13.1 4.64 C 12.62 4.93 12.25 5.35 11.97 5.91 C 11.69 6.47 11.55 7.16 11.55 7.98 C 11.55 8.79 11.69 9.48 11.96 10.05 C 12.24 10.61 12.61 11.03 13.07 11.32 C 13.54 11.61 14.05 11.75 14.61 11.75 C 15.18 11.75 15.67 11.64 16.08 11.41 C 16.5 11.18 16.83 10.86 17.07 10.47 C 17.32 10.07 17.48 9.62 17.53 9.11 L 14.65 9.11 L 14.65 7.79 L 19.02 7.79 C 19.02 8.66 19.02 9.53 19.02 10.39 C 19.02 11.26 19.02 12.13 19.02 12.99 L 17.6 12.99 L 17.6 11.59 L 17.52 11.59 C 17.24 12.08 16.85 12.47 16.34 12.77 C 15.85 13.07 15.24 13.22 14.51 13.22 Z" + android:fillColor="#FF000000"/> + <path + android:pathData="M 24.12 5.24 L 24.12 2.89 L 22.82 2.89 L 22.82 5.24 L 20.47 5.24 L 20.47 6.54 L 22.82 6.54 L 22.82 8.89 L 24.12 8.89 L 24.12 6.54 L 26.47 6.54 L 26.47 5.24 Z" + android:fillColor="#FF000000"/> </vector> diff --git a/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml index e5cdff33fe98..d1f4b6fd818b 100644 --- a/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml @@ -14,23 +14,20 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="22.94dp" - android:height="15dp" - android:viewportWidth="26" - android:viewportHeight="17"> - - <path - android:fillColor="#FFFFFFFF" - android:pathData="M1.59,12.4h3.9v1.07H0.33V3.52h1.26V12.4z" /> + android:width="31dp" + android:height="16dp" + android:viewportWidth="31.0" + android:viewportHeight="16.0"> <path - android:fillColor="#FFFFFFFF" - android:pathData="M11.35,4.6H8.73v8.88H7.48V4.6H4.87V3.52h6.48V4.6z" /> + android:fillColor="#FF000000" + android:pathData="M2,13V2.98h1.53v8.57H8.3V13H2z"/> <path - android:fillColor="#FFFFFFFF" - android:pathData="M17.59,8.88h-3.52v3.53h4.1v1.07h-5.35V3.52h5.28V4.6h-4.03V7.8h3.52V8.88z" /> + android:fillColor="#FF000000" + android:pathData="M11.24,13V4.43H8.19V2.98h7.63v1.46h-3.05V13H11.24z"/> <path - android:fillColor="#FFFFFFFF" - android:pathData="M 23.32 5.74 L 23.32 3.39 L 22.02 3.39 L 22.02 5.74 L 19.67 5.74 L 19.67 7.04 L 22.02 7.04 L 22.02 9.39 L 23.32 9.39 L 23.32 7.04 L 25.67 7.04 L 25.67 5.74 Z" /> + android:fillColor="#FF000000" + android:pathData="M17.41,13V2.98h6.36v1.46h-4.83v2.65h4.4v1.46h-4.4v3.01h4.83V13H17.41z"/> <path - android:pathData="M 0 0 H 26 V 17 H 0 V 0 Z" /> + android:fillColor="#FF000000" + android:pathData="M28.72 5.24 28.72 2.89 27.42 2.89 27.42 5.24 25.07 5.24 25.07 6.54 27.42 6.54 27.42 8.89 28.72 8.89 28.72 6.54 31.07 6.54 31.07 5.24Z"/> </vector> diff --git a/packages/SettingsLib/res/values/config_qti.xml b/packages/SettingsLib/res/values/config_qti.xml index b2bcab34db3b..ff999e09ce91 100644 --- a/packages/SettingsLib/res/values/config_qti.xml +++ b/packages/SettingsLib/res/values/config_qti.xml @@ -34,6 +34,6 @@ <bool name="config_showRsrpSignalLevelforLTE">false</bool> <bool name="config_alwaysShowTypeIcon">false</bool> <bool name="config_hideNoInternetState">false</bool> - <bool name="config_display_volte">true</bool> + <bool name="config_display_volte">false</bool> <bool name="config_display_vowifi">false</bool> </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 6eb2f3834858..48e54a4d5ef4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -750,6 +750,10 @@ public class ApplicationsState { } return null; } + if (info.sourceDir == null) { + // Avoid NullPointerException for broken uninstalled packages. + return null; + } if (DEBUG) { Log.i(TAG, "Creating AppEntry for " + info.packageName); } diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java index 1251b0dc306a..5726c7996547 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java @@ -26,6 +26,7 @@ import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE; import static android.os.BatteryManager.EXTRA_PLUGGED; import static android.os.BatteryManager.EXTRA_PRESENT; import static android.os.BatteryManager.EXTRA_STATUS; +import static android.os.BatteryManager.EXTRA_OEM_FAST_CHARGER; import android.content.Context; import android.content.Intent; @@ -52,6 +53,7 @@ public class BatteryStatus { public final int plugged; public final int chargingStatus; public final int maxChargingWattage; + public final boolean oemFastChargeStatus; public final boolean present; public final Optional<Boolean> incompatibleCharger; @@ -62,12 +64,13 @@ public class BatteryStatus { } public BatteryStatus(int status, int level, int plugged, int chargingStatus, - int maxChargingWattage, boolean present) { + int maxChargingWattage, boolean oemFastChargeStatus, boolean present) { this.status = status; this.level = level; this.plugged = plugged; this.chargingStatus = chargingStatus; this.maxChargingWattage = maxChargingWattage; + this.oemFastChargeStatus = oemFastChargeStatus; this.present = present; this.incompatibleCharger = Optional.empty(); } @@ -87,6 +90,7 @@ public class BatteryStatus { level = getBatteryLevel(batteryChangedIntent); chargingStatus = batteryChangedIntent.getIntExtra(EXTRA_CHARGING_STATUS, CHARGING_POLICY_DEFAULT); + oemFastChargeStatus = batteryChangedIntent.getBooleanExtra(EXTRA_OEM_FAST_CHARGER, false); present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true); this.incompatibleCharger = incompatibleCharger; @@ -150,6 +154,9 @@ public class BatteryStatus { /** Return current chargin speed is fast, slow or normal. */ public final int getChargingSpeed(Context context) { + if (oemFastChargeStatus) { + return CHARGING_FAST; + } final int slowThreshold = context.getResources().getInteger( R.integer.config_chargingSlowlyThreshold); final int fastThreshold = context.getResources().getInteger( diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index ea585a2eb46a..9cbdd82d786c 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -196,6 +196,7 @@ android_library { "motion_tool_lib", ], manifest: "AndroidManifest.xml", + additional_manifests: ["IceManifest.xml"], defaults: [ "SystemUI_compose_defaults", ], diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 6ed3fc774252..c375527f325d 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -481,7 +481,7 @@ <activity android:name=".tuner.TunerActivity" android:enabled="false" android:icon="@drawable/tuner" - android:theme="@style/TunerSettings" + android:theme="@style/Theme.SubSettingsBase" android:label="@string/system_ui_tuner" android:process=":tuner" android:exported="true"> @@ -498,7 +498,7 @@ <activity-alias android:name=".DemoMode" android:targetActivity=".tuner.TunerActivity" android:icon="@drawable/tuner" - android:theme="@style/TunerSettings" + android:theme="@style/Theme.SubSettingsBase" android:label="@string/demo_mode" android:process=":tuner" android:exported="true"> diff --git a/packages/SystemUI/IceManifest.xml b/packages/SystemUI/IceManifest.xml new file mode 100644 index 000000000000..74638926a7e6 --- /dev/null +++ b/packages/SystemUI/IceManifest.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.systemui"> + + <!-- SystemUI Tuner --> + <application> + <activity-alias + android:name=".tuner.StatusBarTuner" + android:targetActivity=".tuner.TunerActivity" + android:icon="@drawable/tuner" + android:theme="@style/Theme.SubSettingsBase" + android:label="@string/status_bar_icons_title" + android:process=":tuner" + android:exported="true"> + <intent-filter> + <action android:name="com.android.settings.action.STATUS_BAR_TUNER" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity-alias> + </application> + +</manifest> diff --git a/packages/SystemUI/customization/res/font/clock.xml b/packages/SystemUI/customization/res/font/clock.xml new file mode 100644 index 000000000000..1074ef163c84 --- /dev/null +++ b/packages/SystemUI/customization/res/font/clock.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 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. +*/ +--> + +<!-- +** AOD/LockScreen Clock font. +** Should include all numeric glyphs in all supported locales. +** Recommended: font with variable width to support AOD => LS animations +--> +<font-family xmlns:android="http://schemas.android.com/apk/res/android"> + <font android:font="@font/google_sans_clock"/> +</font-family> diff --git a/packages/SystemUI/customization/res/font/google_sans_clock.ttf b/packages/SystemUI/customization/res/font/google_sans_clock.ttf Binary files differnew file mode 100644 index 000000000000..5e683a05088c --- /dev/null +++ b/packages/SystemUI/customization/res/font/google_sans_clock.ttf diff --git a/packages/SystemUI/customization/res/layout/clock_default_large.xml b/packages/SystemUI/customization/res/layout/clock_default_large.xml index 0139d50dcfba..415f964a215f 100644 --- a/packages/SystemUI/customization/res/layout/clock_default_large.xml +++ b/packages/SystemUI/customization/res/layout/clock_default_large.xml @@ -23,7 +23,7 @@ android:layout_gravity="center" android:gravity="center_horizontal" android:textSize="@dimen/large_clock_text_size" - android:fontFamily="@*android:string/config_clockFontFamily" + android:fontFamily="@font/clock" android:typeface="monospace" android:elegantTextHeight="false" chargeAnimationDelay="200" diff --git a/packages/SystemUI/customization/res/layout/clock_default_small.xml b/packages/SystemUI/customization/res/layout/clock_default_small.xml index ff6d7f9e2240..eb86ae50cbc9 100644 --- a/packages/SystemUI/customization/res/layout/clock_default_small.xml +++ b/packages/SystemUI/customization/res/layout/clock_default_small.xml @@ -23,7 +23,7 @@ android:layout_gravity="start" android:gravity="start" android:textSize="@dimen/small_clock_text_size" - android:fontFamily="@*android:string/config_clockFontFamily" + android:fontFamily="@font/clock" android:elegantTextHeight="false" android:ellipsize="none" android:singleLine="true" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml index 7c5dbc247428..64657547621f 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml @@ -38,7 +38,7 @@ android:id="@+id/row" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" + android:orientation="vertical" android:gravity="start" /> </com.android.keyguard.KeyguardSliceView> diff --git a/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png b/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png Binary files differnew file mode 100644 index 000000000000..4102e28c1300 --- /dev/null +++ b/packages/SystemUI/res/drawable-nodpi/udfps_icon_pressed.png diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml new file mode 100644 index 000000000000..7dddc9d0e930 --- /dev/null +++ b/packages/SystemUI/res/drawable/dialog_tri_state_down_bg.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 CypherOS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <solid android:color="#ff1d1d1d" /> + <corners + android:topLeftRadius="@dimen/tri_state_down_top_left_radius" + android:topRightRadius="@dimen/tri_state_down_top_right_radius" + android:bottomLeftRadius="@dimen/tri_state_down_bottom_left_radius" + android:bottomRightRadius="@dimen/tri_state_down_bottom_right_radius" /> + </shape> + </item> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml new file mode 100644 index 000000000000..7cde6be2808c --- /dev/null +++ b/packages/SystemUI/res/drawable/dialog_tri_state_middle_bg.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 CypherOS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <solid android:color="#ff1d1d1d" /> + <corners + android:topLeftRadius="@dimen/tri_state_mid_top_left_radius" + android:topRightRadius="@dimen/tri_state_mid_top_right_radius" + android:bottomLeftRadius="@dimen/tri_state_mid_bottom_left_radius" + android:bottomRightRadius="@dimen/tri_state_mid_bottom_right_radius" /> + </shape> + </item> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml b/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml new file mode 100644 index 000000000000..69757a77ee86 --- /dev/null +++ b/packages/SystemUI/res/drawable/dialog_tri_state_up_bg.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 CypherOS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape> + <solid android:color="#ff1d1d1d" /> + <corners + android:topLeftRadius="@dimen/tri_state_up_top_left_radius" + android:topRightRadius="@dimen/tri_state_up_top_right_radius" + android:bottomLeftRadius="@dimen/tri_state_up_bottom_left_radius" + android:bottomRightRadius="@dimen/tri_state_up_bottom_right_radius" /> + </shape> + </item> +</layer-list>
\ No newline at end of file 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 000000000000..4bb2d4ac566b --- /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 000000000000..2c3ba974a7e1 --- /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_heads_up.xml b/packages/SystemUI/res/drawable/ic_qs_heads_up.xml new file mode 100644 index 000000000000..b107602787c1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_heads_up.xml @@ -0,0 +1,36 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <path + android:pathData="M0,0h24v24H0V0z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M18,16v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-0.83-0.68-1.5-1.51-1.5S10.5,3.17,10.5,4v0.68C7.63,5.36,6,7.92,6,11v5 l-1.3,1.29C4.07,17.92,4.51,19,5.4,19h13.17c0.89,0,1.34-1.08,0.71-1.71L18,16z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.99,22c1.1,0,2-0.9,2-2h-4C9.99,21.1,10.88,22,11.99,22z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M6.77,4.73C7.19,4.35,7.2,3.7,6.8,3.3l0,0c-0.38-0.38-1-0.39-1.39-0.02C3.7,4.84,2.52,6.96,2.14,9.34 C2.05,9.95,2.52,10.5,3.14,10.5h0c0.48,0,0.9-0.35,0.98-0.83C4.42,7.73,5.38,6,6.77,4.73z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M18.6,3.28c-0.4-0.37-1.02-0.36-1.4,0.02l0,0c-0.4,0.4-0.38,1.04,0.03,1.42c1.38,1.27,2.35,3,2.65,4.94 c0.07,0.48,0.49,0.83,0.98,0.83c0.61,0,1.09-0.55,0.99-1.16C21.47,6.96,20.3,4.85,18.6,3.28z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_speaker_group_24dp.xml b/packages/SystemUI/res/drawable/ic_speaker_group_24dp.xml new file mode 100644 index 000000000000..37475e52010a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_speaker_group_24dp.xml @@ -0,0 +1,22 @@ +<!-- + Copyright (C) 2020-2022 The Android Open Source Project + + SPDX-License-Identifier: Apache-2.0 +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?android:attr/colorBackgroundFloating"> + <path + android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z" + android:fillColor="@android:color/white"/> + <path + android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0" + android:fillColor="@android:color/white"/> + <path + android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z" + android:fillColor="@android:color/white"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_airplanemode.xml b/packages/SystemUI/res/drawable/ic_statusbar_airplanemode.xml new file mode 100644 index 000000000000..7ade8b215590 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_airplanemode.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="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:pathData="M21,16v-2l-8,-5V3.5C13,2.67 12.33,2 11.5,2S10,2.67 10,3.5V9l-8,5v2l8,-2.5V19l-2,1.5V22l3.5,-1l3.5,1v-1.5L13,19v-5.5L21,16z" + android:fillColor="#FFFFFFFF"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_alarm.xml b/packages/SystemUI/res/drawable/ic_statusbar_alarm.xml new file mode 100644 index 000000000000..4d0a5f8c7346 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_alarm.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_statusbar_auto_rotate.xml new file mode 100644 index 000000000000..9a2cb496d282 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_auto_rotate.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:height="24dp" + android:width="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7.4,10.94H2.45V5.99l2,0.01v1.53l4.61,-4.61c0.64,-0.64 1.67,-0.66 2.29,-0.04l8.18,8.18h-2.83l-6.48,-6.48L5.86,8.95H7.4V10.94zM16.6,13.06l0.01,2h1.53l-4.36,4.36l-6.48,-6.48H4.46l8.19,8.19c0.62,0.62 1.65,0.6 2.29,-0.04l4.61,-4.61l0.01,0.01v1.53h1.99v-4.95H16.6z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_camera.xml b/packages/SystemUI/res/drawable/ic_statusbar_camera.xml new file mode 100644 index 000000000000..32d6b5326ffc --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_camera.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_cast.xml b/packages/SystemUI/res/drawable/ic_statusbar_cast.xml new file mode 100644 index 000000000000..5413c77215df --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_cast.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="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_clock.xml b/packages/SystemUI/res/drawable/ic_statusbar_clock.xml new file mode 100644 index 000000000000..4b91508d2eb1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_clock.xml @@ -0,0 +1,28 @@ +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.99,2.0C6.47,2.0 2.0,6.48 2.0,12.0s4.47,10.0 9.99,10.0C17.52,22.0 22.0,17.52 22.0,12.0S17.52,2.0 11.99,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.58 -8.0,-8.0s3.58,-8.0 8.0,-8.0 8.0,3.58 8.0,8.0 -3.58,8.0 -8.0,8.0z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.5,7.0L11.0,7.0l0.0,6.0l5.25,3.1 0.75,-1.23 -4.5,-2.67z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_do_not_disturb.xml b/packages/SystemUI/res/drawable/ic_statusbar_do_not_disturb.xml new file mode 100644 index 000000000000..cace8d4433f5 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_do_not_disturb.xml @@ -0,0 +1,28 @@ +<!-- + Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10c5.52,0 10,-4.48 10,-10C22,6.48 17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8c0,-4.41 3.59,-8 8,-8c4.41,0 8,3.59 8,8C20,16.41 16.41,20 12,20z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7,11h10v2h-10z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_ethernet.xml b/packages/SystemUI/res/drawable/ic_statusbar_ethernet.xml new file mode 100644 index 000000000000..46e753fd7eb8 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_ethernet.xml @@ -0,0 +1,34 @@ + <!-- + ~ 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. + --> + <vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M17,6l-1.41,1.41L20.17,12l-4.58,4.59L17,18l6,-6zM8.41,7.41L7,6l-6,6 6,6 1.41,-1.41L3.83,12z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M8,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M16,12m-1,0a1,1 0,1 1,2 0a1,1 0,1 1,-2 0"/> + </vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_headset.xml b/packages/SystemUI/res/drawable/ic_statusbar_headset.xml new file mode 100644 index 000000000000..ad9a55fcc5e2 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_headset.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M19,15v3c0,0.55 -0.45,1 -1,1h-1v-4h2M7,15v4H6c-0.55,0 -1,-0.45 -1,-1v-3h2m5,-13c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_hotspot.xml b/packages/SystemUI/res/drawable/ic_statusbar_hotspot.xml new file mode 100644 index 000000000000..37f5ea9075ae --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_hotspot.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,7c-3.31,0-6,2.69-6,6c0,1.66,0.68,3.15,1.76,4.24l1.42-1.42C8.45,15.1,8,14.11,8,13c0-2.21,1.79-4,4-4s4,1.79,4,4 c0,1.11-0.45,2.1-1.18,2.82l1.42,1.42C17.32,16.15,18,14.66,18,13C18,9.69,15.31,7,12,7z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,3C6.48,3,2,7.48,2,13c0,2.76,1.12,5.26,2.93,7.07l1.41-1.41C4.9,17.21,4,15.21,4,13c0-4.42,3.58-8,8-8s8,3.58,8,8 c0,2.21-0.9,4.2-2.35,5.65l1.41,1.41C20.88,18.26,22,15.76,22,13C22,7.48,17.52,3,12,3z" /> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12,11c-1.1,0-2,0.9-2,2c0,0.55,0.23,1.05,0.59,1.41C10.95,14.77,11.45,15,12,15s1.05-0.23,1.41-0.59 C13.77,14.05,14,13.55,14,13C14,11.9,13.1,11,12,11z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_mobile_network.xml b/packages/SystemUI/res/drawable/ic_statusbar_mobile_network.xml new file mode 100644 index 000000000000..1f24717a1512 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_mobile_network.xml @@ -0,0 +1,26 @@ +<!-- + 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:autoMirrored="true" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:pathData="m3.8,22l17.19,0c0.55,0 1.01,-0.45 1.01,-1.01l0,-17.19c0,-0.71 -0.87,-1.08 -1.38,-0.57l-17.38,17.39c-0.51,0.51 -0.15,1.38 0.56,1.38z" + android:fillColor="#FFFFFFFF"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_mute.xml b/packages/SystemUI/res/drawable/ic_statusbar_mute.xml new file mode 100644 index 000000000000..c63aeea9489e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_mute.xml @@ -0,0 +1,26 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_priority.xml b/packages/SystemUI/res/drawable/ic_statusbar_priority.xml new file mode 100644 index 000000000000..adcbbe932ec6 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_priority.xml @@ -0,0 +1,27 @@ +<?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. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M15,19L3,19l4.5,-7L3,5h12c0.65,0 1.26,0.31 1.63,0.84L21,12l-4.37,6.16c-0.37,0.52 -0.98,0.84 -1.63,0.84zM6.5,17L15,17l3.5,-5L15,7L6.5,7l3.5,5 -3.5,5z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_vibrate.xml b/packages/SystemUI/res/drawable/ic_statusbar_vibrate.xml new file mode 100644 index 000000000000..dfa60992ba51 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_vibrate.xml @@ -0,0 +1,26 @@ +<!-- +Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_wifi.xml b/packages/SystemUI/res/drawable/ic_statusbar_wifi.xml new file mode 100644 index 000000000000..e56e9512c9b5 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_wifi.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M24,7.39L12,22L0,7.39C2.97,4.08,7.25,2,12,2S21.03,4.08,24,7.39z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_statusbar_work.xml b/packages/SystemUI/res/drawable/ic_statusbar_work.xml new file mode 100644 index 000000000000..ea8918b1ca12 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_statusbar_work.xml @@ -0,0 +1,26 @@ +<?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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM12,15c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM14,6h-4L10,4h4v2z" + android:fillColor="#FFFFFFFF"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_vpn_key.xml b/packages/SystemUI/res/drawable/ic_vpn_key.xml new file mode 100644 index 000000000000..c2a7e342397e --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_vpn_key.xml @@ -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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/> +</vector> diff --git a/packages/SystemUI/res/drawable/stat_sys_dnd.xml b/packages/SystemUI/res/drawable/stat_sys_dnd.xml index aa352b42cf04..21bdb64db0bf 100644 --- a/packages/SystemUI/res/drawable/stat_sys_dnd.xml +++ b/packages/SystemUI/res/drawable/stat_sys_dnd.xml @@ -17,6 +17,6 @@ */ --> <inset xmlns:android="http://schemas.android.com/apk/res/android" - android:insetLeft="2.5dp" - android:insetRight="2.5dp" + android:insetLeft="0.5dp" + android:insetRight="0.5dp" android:drawable="@*android:drawable/ic_qs_dnd" />
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml index 4a9d41fae1d5..13dc8a978a38 100644 --- a/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml +++ b/packages/SystemUI/res/drawable/stat_sys_ringer_silent.xml @@ -14,6 +14,6 @@ Copyright (C) 2015 The Android Open Source Project limitations under the License. --> <inset xmlns:android="http://schemas.android.com/apk/res/android" - android:insetLeft="3dp" - android:insetRight="3dp" + android:insetLeft="-2.5dp" + android:insetRight="-2.5dp" android:drawable="@drawable/ic_speaker_mute" /> diff --git a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml index 21a4c1703d31..e3b22970d803 100644 --- a/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml +++ b/packages/SystemUI/res/drawable/stat_sys_ringer_vibrate.xml @@ -14,6 +14,4 @@ limitations under the License. --> <inset xmlns:android="http://schemas.android.com/apk/res/android" - android:insetLeft="2.5dp" - android:insetRight="2.5dp" android:drawable="@drawable/ic_volume_ringer_vibrate" />
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/volume_background.xml b/packages/SystemUI/res/drawable/volume_background.xml new file mode 100644 index 000000000000..671d45ce9006 --- /dev/null +++ b/packages/SystemUI/res/drawable/volume_background.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The LineageOS Project + + SPDX-License-Identifier: Apache-2.0 +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <size android:width="@dimen/volume_dialog_panel_width" /> + <solid android:color="?androidprv:attr/colorSurface" /> +</shape> diff --git a/packages/SystemUI/res/font b/packages/SystemUI/res/font new file mode 120000 index 000000000000..2acf8c302a6d --- /dev/null +++ b/packages/SystemUI/res/font @@ -0,0 +1 @@ +../customization/res/font
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml index 3b70dc060e84..c7bb90278d6e 100644 --- a/packages/SystemUI/res/layout-land/volume_dialog.xml +++ b/packages/SystemUI/res/layout-land/volume_dialog.xml @@ -21,18 +21,17 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" android:background="@android:color/transparent" android:theme="@style/volume_dialog_theme"> <!-- right-aligned to be physically near volume button --> - <LinearLayout + <com.android.systemui.animation.view.LaunchableLinearLayout android:id="@+id/volume_dialog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" - android:layout_marginRight="@dimen/volume_dialog_panel_transparent_padding_right" + android:layout_marginLeft="@dimen/volume_dialog_panel_transparent_padding_horizontal" + android:layout_marginRight="@dimen/volume_dialog_panel_transparent_padding_horizontal" android:orientation="vertical" android:clipToPadding="false" android:clipChildren="false"> @@ -55,7 +54,6 @@ android:layout_height="@dimen/volume_dialog_ringer_size" android:layout_marginBottom="@dimen/volume_dialog_spacer" android:gravity="right" - android:layout_gravity="right" android:translationZ="@dimen/volume_dialog_elevation" android:clipToPadding="false" android:background="@drawable/rounded_bg_full"> @@ -83,7 +81,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" android:orientation="vertical" android:clipChildren="false" android:clipToPadding="false" > @@ -99,13 +96,12 @@ android:id="@+id/settings_container" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/volume_background_bottom" + android:background="@drawable/volume_background" android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" - android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding" android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings" - android:src="@drawable/horizontal_ellipsis" + android:src="@drawable/ic_speaker_group_24dp" android:layout_width="@dimen/volume_dialog_tap_target_size" android:layout_height="@dimen/volume_dialog_tap_target_size" android:layout_gravity="center" @@ -114,6 +110,38 @@ android:tint="?androidprv:attr/colorAccent" android:soundEffectsEnabled="false" /> </FrameLayout> + <FrameLayout + android:id="@+id/expandable_indicator_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/volume_background_bottom" + android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" + android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding" + android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> + <com.android.systemui.statusbar.phone.ExpandableIndicator + android:id="@+id/expandable_indicator" + android:layout_width="@dimen/volume_dialog_tap_target_size" + android:layout_height="@dimen/volume_dialog_tap_target_size" + android:layout_gravity="center" + android:contentDescription="@string/accessibility_volume_settings" + android:background="@drawable/ripple_drawable_20dp" + android:tint="?androidprv:attr/colorAccent" + android:soundEffectsEnabled="false" + android:padding="10dp" + android:rotation="90" /> + </FrameLayout> + <FrameLayout + android:id="@+id/rounded_border_bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/volume_background_bottom" + android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" + android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> + <View + android:layout_width="0dp" + android:layout_height="32dp" + android:background="@drawable/ripple_drawable_20dp"/> + </FrameLayout> </LinearLayout> </LinearLayout> @@ -124,7 +152,6 @@ android:layout_height="@dimen/volume_dialog_caption_size" android:layout_marginTop="@dimen/volume_dialog_row_margin_bottom" android:gravity="right" - android:layout_gravity="right" android:clipToPadding="false" android:clipToOutline="true" android:background="@drawable/volume_row_rounded_background"> @@ -138,7 +165,7 @@ android:layout_gravity="center" android:soundEffectsEnabled="false" /> </FrameLayout> - </LinearLayout> + </com.android.systemui.animation.view.LaunchableLinearLayout> <ViewStub android:id="@+id/odi_captions_tooltip_stub" @@ -146,7 +173,8 @@ android:layout="@layout/volume_tool_tip_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom | right" - android:layout_marginRight="@dimen/volume_tool_tip_right_margin"/> + android:layout_gravity="bottom" + android:layout_marginLeft="@dimen/volume_tool_tip_horizontal_margin" + android:layout_marginRight="@dimen/volume_tool_tip_horizontal_margin"/> </FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml index 8bff1a135336..64e345e8a825 100644 --- a/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml +++ b/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml @@ -24,7 +24,7 @@ android:id="@+id/time_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:fontFamily="@*android:string/config_clockFontFamily" + android:fontFamily="@font/clock" android:textColor="@android:color/white" android:format12Hour="@string/dream_time_complication_12_hr_time_format" android:format24Hour="@string/dream_time_complication_24_hr_time_format" diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml index 3be99939ba0f..53af93295189 100644 --- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml +++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml @@ -56,10 +56,4 @@ android:importantForAccessibility="auto" /> </com.android.keyguard.AlphaOptimizedLinearLayout> - <View - android:id="@+id/nav_bar_background" - android:layout_width="match_parent" - android:layout_height="@dimen/navigation_bar_size" - android:layout_gravity="bottom" - android:background="#ff000000" /> </merge> diff --git a/packages/SystemUI/res/layout/tri_state_dialog.xml b/packages/SystemUI/res/layout/tri_state_dialog.xml new file mode 100644 index 000000000000..cf3890d59a88 --- /dev/null +++ b/packages/SystemUI/res/layout/tri_state_dialog.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 CypherOS + + 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. +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:paddingLeft="@dimen/tri_state_dialog_padding" + android:paddingTop="@dimen/tri_state_dialog_padding" + android:paddingRight="@dimen/tri_state_dialog_padding" + android:paddingBottom="@dimen/tri_state_dialog_padding" + android:clipToPadding="false" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true"> + + <LinearLayout + android:layout_gravity="center|right" + android:orientation="horizontal" + android:id="@+id/tri_state_layout" + android:background="@drawable/dialog_tri_state_middle_bg" + android:layout_width="wrap_content" + android:layout_height="48.0dip" + android:translationZ="@dimen/tri_state_dialog_elevation"> + + <FrameLayout + android:layout_width="54.0dip" + android:layout_height="fill_parent"> + + <ImageView + android:layout_gravity="center" + android:id="@+id/tri_state_icon" + android:layout_marginLeft="2.0dip" + android:layout_width="@dimen/tri_state_dialog_icon_size" + android:layout_height="@dimen/tri_state_dialog_icon_size" /> + </FrameLayout> + + <TextView + android:gravity="center_vertical" + android:id="@+id/tri_state_text" + android:layout_width="wrap_content" + android:layout_height="fill_parent" + style="@style/TriStateUiText" /> + + <FrameLayout + android:layout_width="18.0dip" + android:layout_height="fill_parent" /> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/tuner_activity.xml b/packages/SystemUI/res/layout/tuner_activity.xml index 83cbf14edd39..7e91267d7ae6 100644 --- a/packages/SystemUI/res/layout/tuner_activity.xml +++ b/packages/SystemUI/res/layout/tuner_activity.xml @@ -20,13 +20,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> - <Toolbar - android:id="@+id/action_bar" - style="?android:attr/actionBarStyle" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:theme="?android:attr/actionBarTheme" - android:navigationContentDescription="@*android:string/action_bar_up_description" /> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/udfps_view.xml b/packages/SystemUI/res/layout/udfps_view.xml index 257d238f5c54..0fcbfa161ddf 100644 --- a/packages/SystemUI/res/layout/udfps_view.xml +++ b/packages/SystemUI/res/layout/udfps_view.xml @@ -28,4 +28,10 @@ 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.UdfpsView> diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index 6a192d4b7e05..ffbb63bea855 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -21,18 +21,17 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" android:clipToPadding="false" android:theme="@style/volume_dialog_theme"> <!-- right-aligned to be physically near volume button --> - <LinearLayout + <com.android.systemui.animation.view.LaunchableLinearLayout android:id="@+id/volume_dialog" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" - android:layout_marginRight="@dimen/volume_dialog_panel_transparent_padding_right" + android:layout_marginLeft="@dimen/volume_dialog_panel_transparent_padding_horizontal" + android:layout_marginRight="@dimen/volume_dialog_panel_transparent_padding_horizontal" android:orientation="vertical" android:clipToPadding="false" android:clipChildren="false"> @@ -54,7 +53,6 @@ android:layout_height="@dimen/volume_dialog_ringer_size" android:layout_marginBottom="@dimen/volume_dialog_spacer" android:gravity="right" - android:layout_gravity="right" android:translationZ="@dimen/volume_dialog_elevation" android:clipToPadding="false" android:background="@drawable/rounded_bg_full"> @@ -82,7 +80,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" - android:layout_gravity="right" android:orientation="vertical" android:clipChildren="false" android:clipToPadding="false" > @@ -98,13 +95,12 @@ android:id="@+id/settings_container" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/volume_background_bottom" + android:background="@drawable/volume_background" android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" - android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding" android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> <com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings" - android:src="@drawable/horizontal_ellipsis" + android:src="@drawable/ic_speaker_group_24dp" android:layout_width="@dimen/volume_dialog_tap_target_size" android:layout_height="@dimen/volume_dialog_tap_target_size" android:layout_gravity="center" @@ -113,6 +109,38 @@ android:tint="?androidprv:attr/colorAccent" android:soundEffectsEnabled="false" /> </FrameLayout> + <FrameLayout + android:id="@+id/expandable_indicator_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/volume_background_bottom" + android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" + android:paddingBottom="@dimen/volume_dialog_ringer_rows_padding" + android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> + <com.android.systemui.statusbar.phone.ExpandableIndicator + android:id="@+id/expandable_indicator" + android:layout_width="@dimen/volume_dialog_tap_target_size" + android:layout_height="@dimen/volume_dialog_tap_target_size" + android:layout_gravity="center" + android:contentDescription="@string/accessibility_volume_settings" + android:background="@drawable/ripple_drawable_20dp" + android:tint="?androidprv:attr/colorAccent" + android:soundEffectsEnabled="false" + android:padding="10dp" + android:rotation="90" /> + </FrameLayout> + <FrameLayout + android:id="@+id/rounded_border_bottom" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:background="@drawable/volume_background_bottom" + android:paddingLeft="@dimen/volume_dialog_ringer_rows_padding" + android:paddingRight="@dimen/volume_dialog_ringer_rows_padding"> + <View + android:layout_width="0dp" + android:layout_height="32dp" + android:background="@drawable/ripple_drawable_20dp"/> + </FrameLayout> </LinearLayout> </LinearLayout> @@ -123,7 +151,6 @@ android:layout_height="@dimen/volume_dialog_caption_size" android:layout_marginTop="@dimen/volume_dialog_row_margin_bottom" android:gravity="right" - android:layout_gravity="right" android:clipToPadding="false" android:clipToOutline="true" android:background="@drawable/volume_row_rounded_background"> @@ -137,7 +164,7 @@ android:layout_gravity="center" android:soundEffectsEnabled="false"/> </FrameLayout> - </LinearLayout> + </com.android.systemui.animation.view.LaunchableLinearLayout> <ViewStub android:id="@+id/odi_captions_tooltip_stub" @@ -145,7 +172,8 @@ android:layout="@layout/volume_tool_tip_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom | right" - android:layout_marginRight="@dimen/volume_tool_tip_right_margin"/> + android:layout_gravity="bottom" + android:layout_marginLeft="@dimen/volume_tool_tip_horizontal_margin" + android:layout_marginRight="@dimen/volume_tool_tip_horizontal_margin"/> </FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 4fc98b48bfde..e4bdb180aa19 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -91,7 +91,7 @@ <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> - internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling + internet,bt,flashlight,dnd,alarm,airplane,nfc,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling,aod,caffeine,heads_up </string> <!-- The tiles to display in QuickSettings --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 44a5c07502ac..85a9b3c0839e 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -485,7 +485,7 @@ <dimen name="brightness_mirror_height">48dp</dimen> - <dimen name="volume_dialog_panel_transparent_padding_right">8dp</dimen> + <dimen name="volume_dialog_panel_transparent_padding_horizontal">8dp</dimen> <dimen name="volume_dialog_panel_transparent_padding">20dp</dimen> @@ -524,7 +524,7 @@ <dimen name="volume_dialog_background_blur_radius">0dp</dimen> - <dimen name="volume_tool_tip_right_margin">76dp</dimen> + <dimen name="volume_tool_tip_horizontal_margin">76dp</dimen> <dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen> diff --git a/packages/SystemUI/res/values/ice_config.xml b/packages/SystemUI/res/values/ice_config.xml new file mode 100644 index 000000000000..563d63f7ac2a --- /dev/null +++ b/packages/SystemUI/res/values/ice_config.xml @@ -0,0 +1,22 @@ +<!-- + Copyright (C) 2022 Project ICE + + 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> + <!-- Color of the UDFPS pressed view --> + <color name="config_udfpsColor">#ffffffff</color> + + <!-- Allow devices override audio panel location to the left side --> + <bool name="config_audioPanelOnLeftSide">false</bool> +</resources> diff --git a/packages/SystemUI/res/values/ice_dimens.xml b/packages/SystemUI/res/values/ice_dimens.xml new file mode 100644 index 000000000000..f81dc4ae7797 --- /dev/null +++ b/packages/SystemUI/res/values/ice_dimens.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 Project ICE + + 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"> + <!-- Alert Slider --> + <dimen name="tri_state_down_dialog_position">0px</dimen> + <dimen name="tri_state_down_dialog_position_l">0px</dimen> + <dimen name="tri_state_middle_dialog_position">0px</dimen> + <dimen name="tri_state_middle_dialog_position_l">0px</dimen> + <dimen name="tri_state_up_dialog_position">0px</dimen> + <dimen name="tri_state_up_dialog_position_l">0px</dimen> + <dimen name="tri_state_up_dialog_position_deep">0px</dimen> + <dimen name="tri_state_up_dialog_position_deep_land">0px</dimen> + <dimen name="tri_state_dialog_elevation">4.0dip</dimen> + <dimen name="tri_state_dialog_icon_size">24.0dip</dimen> + <dimen name="tri_state_dialog_padding">8.0dip</dimen> + <dimen name="tri_state_down_bottom_left_radius">24.0dip</dimen> + <dimen name="tri_state_down_bottom_right_radius">24.0dip</dimen> + <dimen name="tri_state_down_top_left_radius">24.0dip</dimen> + <dimen name="tri_state_down_top_right_radius">0.0dip</dimen> + <dimen name="tri_state_mid_bottom_left_radius">24.0dip</dimen> + <dimen name="tri_state_mid_bottom_right_radius">24.0dip</dimen> + <dimen name="tri_state_mid_top_left_radius">24.0dip</dimen> + <dimen name="tri_state_mid_top_right_radius">24.0dip</dimen> + <dimen name="tri_state_up_bottom_left_radius">24.0dip</dimen> + <dimen name="tri_state_up_bottom_right_radius">0.0dip</dimen> + <dimen name="tri_state_up_top_left_radius">24.0dip</dimen> + <dimen name="tri_state_up_top_right_radius">24.0dip</dimen> +</resources> diff --git a/packages/SystemUI/res/values/ice_strings.xml b/packages/SystemUI/res/values/ice_strings.xml new file mode 100644 index 000000000000..66948283c9bc --- /dev/null +++ b/packages/SystemUI/res/values/ice_strings.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + Copyright (C) 2022 Project ICE + + 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"> + <!-- Status bar - icons --> + <string name="status_bar_icons_title">Status bar icons</string> + <string name="status_bar_vpn">VPN</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> + + <!-- Custom QS tiles --> + <!-- AOD QS tile --> + <string name="quick_settings_aod_label">AOD</string> + <string name="quick_settings_aod_off_powersave_label">AOD off\nBattery saver</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> + + <!-- Heads up QS tile --> + <string name="quick_settings_heads_up_label">Heads up</string> + <string name="accessibility_quick_settings_heads_up_off">Heads up off.</string> + <string name="accessibility_quick_settings_heads_up_on">Heads up on.</string> +</resources> diff --git a/packages/SystemUI/res/values/ice_styles.xml b/packages/SystemUI/res/values/ice_styles.xml new file mode 100644 index 000000000000..652258a68746 --- /dev/null +++ b/packages/SystemUI/res/values/ice_styles.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 Project ICE + + 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> + <!-- Alert Slider --> + <style name="TriStateUiText"> + <item name="android:textSize">11.0sp</item> + <item name="android:fontFamily">sans-serif-medium</item> + </style> +</resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 5fcde457b09d..a7ef869929de 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -134,7 +134,6 @@ <style name="TextAppearance.QS.TileLabel"> <item name="android:textSize">@dimen/qs_tile_text_size</item> - <item name="android:letterSpacing">0.01</item> <item name="android:lineHeight">20sp</item> <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item> </style> @@ -154,7 +153,6 @@ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">14sp</item> - <item name="android:letterSpacing">0.01</item> </style> <style name="TextAppearance.QS.SecurityFooter" parent="@style/TextAppearance.QS.Status"> @@ -610,7 +608,6 @@ <style name="TextAppearance.QSEdit" > <item name="android:textSize">14sp</item> - <item name="android:letterSpacing">0.01</item> <item name="android:lineHeight">20sp</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> <item name="android:textColor">?android:attr/textColorSecondary</item> diff --git a/packages/SystemUI/res/xml/status_bar_prefs.xml b/packages/SystemUI/res/xml/status_bar_prefs.xml new file mode 100644 index 000000000000..6f4c5bcf10b7 --- /dev/null +++ b/packages/SystemUI/res/xml/status_bar_prefs.xml @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2015 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:sysui="http://schemas.android.com/apk/res-auto" + android:key="status_bar" + android:title="@string/status_bar"> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_auto_rotate" + android:key="rotate" + android:title="@string/status_bar_settings_auto_rotation" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_headset" + android:key="headset" + android:title="@string/headset" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_work" + android:key="managed_profile" + android:title="@string/status_bar_work" /> + + <!-- ime --> + <!-- sync_failing --> + <!-- sync_active --> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_cast" + android:key="cast" + android:title="@string/quick_settings_cast_title" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_hotspot" + android:key="hotspot" + android:title="@string/quick_settings_hotspot_label" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@*android:drawable/ic_qs_bluetooth" + android:key="bluetooth" + android:title="@string/quick_settings_bluetooth_label" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_camera" + android:key="cameratoggle" + android:title="@string/quick_settings_camera_label" /> + + <!-- nfc --> + <!-- tty --> + <!-- speakerphone --> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_do_not_disturb" + android:key="zen" + android:title="@string/quick_settings_dnd_label" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_mute" + android:key="mute" + android:title="@string/volume_ringer_status_silent" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_vibrate" + android:key="volume" + android:title="@string/volume_ringer_status_vibrate" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_wifi" + android:key="wifi" + android:title="@string/quick_settings_wifi_label" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_ethernet" + android:key="ethernet" + android:title="@string/status_bar_ethernet" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_mobile_network" + android:key="mobile" + android:title="@string/quick_settings_cellular_detail_title" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_airplanemode" + android:key="airplane" + android:title="@string/status_bar_airplane" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_vpn_key" + android:key="vpn" + android:title="@string/status_bar_vpn" /> + + <!-- other weird signal stuff --> + + <com.android.systemui.tuner.BatteryPreference + android:icon="@*android:drawable/ic_battery" + android:title="@string/battery" + android:summary="%s" + android:entries="@array/battery_options" /> + + <com.android.systemui.tuner.StatusBarSwitch + android:icon="@drawable/ic_statusbar_alarm" + android:key="alarm_clock" + android:title="@string/status_bar_alarm" /> + + <!-- secure --> + + <com.android.systemui.tuner.ClockPreference + android:icon="@drawable/ic_statusbar_clock" + android:title="@string/tuner_time" + android:summary="%s" + android:entries="@array/clock_options" /> + + <com.android.systemui.tuner.TunerSwitch + android:icon="@drawable/ic_statusbar_priority" + android:key="low_priority" + android:title="@string/tuner_low_priority" + sysui:defValue="false" /> + +</PreferenceScreen> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 902de23a9e2a..aab0b1e8ab51 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -20,94 +20,8 @@ <PreferenceScreen android:key="status_bar" - android:title="@string/status_bar" > - - <com.android.systemui.tuner.StatusBarSwitch - android:key="rotate" - android:title="@string/status_bar_settings_auto_rotation" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="headset" - android:title="@string/headset" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="managed_profile" - android:title="@string/status_bar_work" /> - - <!-- ime --> - <!-- sync_failing --> - <!-- sync_active --> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="cast" - android:title="@string/quick_settings_cast_title" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="hotspot" - android:title="@string/quick_settings_hotspot_label" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="bluetooth" - android:title="@string/quick_settings_bluetooth_label" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="cameratoggle" - android:title="@string/quick_settings_camera_label" /> - - <!-- nfc --> - <!-- tty --> - <!-- speakerphone --> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="zen" - android:title="@string/quick_settings_dnd_label" /> - - <!-- mute --> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="volume" - android:title="@*android:string/volume_unknown" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="wifi" - android:title="@string/quick_settings_wifi_label" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="ethernet" - android:title="@string/status_bar_ethernet" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="mobile" - android:title="@string/quick_settings_cellular_detail_title" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="airplane" - android:title="@string/status_bar_airplane" /> - - <!-- other weird signal stuff --> - - <com.android.systemui.tuner.BatteryPreference - android:title="@string/battery" - android:summary="%s" - android:entries="@array/battery_options" /> - - <com.android.systemui.tuner.StatusBarSwitch - android:key="alarm_clock" - android:title="@string/status_bar_alarm" /> - - <!-- secure --> - - <com.android.systemui.tuner.ClockPreference - android:title="@string/tuner_time" - android:summary="%s" - android:entries="@array/clock_options" /> - - <com.android.systemui.tuner.TunerSwitch - android:key="low_priority" - android:title="@string/tuner_low_priority" - sysui:defValue="false" /> - - </PreferenceScreen> + android:title="@string/status_bar" + android:fragment="com.android.systemui.tuner.StatusBarTuner" /> <PreferenceScreen android:key="volume_and_do_not_disturb" diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index eb75a00dc5a2..33f9ecd03bca 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -16,13 +16,8 @@ package com.android.keyguard; -import android.content.res.Configuration; -import android.telephony.TelephonyManager; - import com.android.systemui.util.ViewController; -import java.util.Locale; - import javax.inject.Inject; /** @@ -31,7 +26,6 @@ import javax.inject.Inject; public class CarrierTextController extends ViewController<CarrierText> { private final CarrierTextManager mCarrierTextManager; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private Locale mLocale; private final CarrierTextManager.CarrierTextCallback mCarrierTextCallback = new CarrierTextManager.CarrierTextCallback() { @Override @@ -62,8 +56,6 @@ public class CarrierTextController extends ViewController<CarrierText> { .setDebugLocationString(mView.getDebugLocation()) .build(); mKeyguardUpdateMonitor = keyguardUpdateMonitor; - mView.setOnConfigurationChangedListener(this::refreshInfoIfNeeded); - mLocale = mView.getResources().getConfiguration().locale; } @Override @@ -81,13 +73,4 @@ public class CarrierTextController extends ViewController<CarrierText> { protected void onViewDetached() { mCarrierTextManager.setListening(null); } - - private void refreshInfoIfNeeded(Configuration newConfig) { - if (mLocale != newConfig.locale) { - mCarrierTextManager.loadCarrierMap(); - mCarrierTextManager.updateCarrierText(); - mLocale = newConfig.locale; - } - - } } diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java index 16b26028d728..b52ee01bfa61 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java @@ -14,12 +14,6 @@ * limitations under the License. */ -/** - * Changes from Qualcomm Innovation Center are provided under the following license: - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause-Clear - */ - package com.android.keyguard; import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ACTIVE_DATA_SUB_CHANGED; @@ -50,10 +44,7 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository; -import com.android.systemui.statusbar.policy.FiveGServiceClient; -import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; import com.android.systemui.telephony.TelephonyListenerManager; -import com.android.systemui.util.CarrierNameCustomization; import java.util.Arrays; import java.util.List; @@ -109,8 +100,7 @@ public class CarrierTextManager { if (callback != null) callback.startedGoingToSleep(); } }; - private FiveGServiceClient mFiveGServiceClient; - private CarrierNameCustomization mCarrierNameCustomization; + @VisibleForTesting protected final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -191,8 +181,8 @@ public class CarrierTextManager { @Main Executor mainExecutor, @Background Executor bgExecutor, KeyguardUpdateMonitor keyguardUpdateMonitor, - CarrierTextManagerLogger logger, - CarrierNameCustomization carrierNameCustomization) { + CarrierTextManagerLogger logger) { + mContext = context; mIsEmergencyCallCapable = telephonyManager.isVoiceCapable(); @@ -218,7 +208,6 @@ public class CarrierTextManager { handleSetListening(mCarrierTextCallback); } }); - mCarrierNameCustomization = carrierNameCustomization; } private TelephonyManager getTelephonyManager() { @@ -318,19 +307,15 @@ public class CarrierTextManager { return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(); } - public void updateCarrierText() { + protected void updateCarrierText() { Trace.beginSection("CarrierTextManager#updateCarrierText"); boolean allSimsMissing = true; boolean anySimReadyAndInService = false; - boolean missingSimsWithSubs = false; - boolean showCustomizeName = getContext().getResources().getBoolean( - com.android.systemui.R.bool.config_show_customize_carrier_name); CharSequence displayText = null; List<SubscriptionInfo> subs = getSubscriptionInfo(); final int numSubs = subs.size(); final int[] subsIds = new int[numSubs]; - if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs); // This array will contain in position i, the index of subscription in slot ID i. // -1 if no subscription in that slot final int[] subOrderBySlot = new int[mSimSlotsNumber]; @@ -347,14 +332,6 @@ public class CarrierTextManager { subOrderBySlot[subs.get(i).getSimSlotIndex()] = i; int simState = mKeyguardUpdateMonitor.getSimState(subId); CharSequence carrierName = subs.get(i).getCarrierName(); - if (showCustomizeName) { - if (mCarrierNameCustomization.isRoamingCustomizationEnabled() - && mCarrierNameCustomization.isRoaming(subId)) { - carrierName = mCarrierNameCustomization.getRoamingCarrierName(subId); - } else { - carrierName = getCustomizeCarrierName(carrierName, subs.get(i)); - } - } CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName); mLogger.logUpdateLoopStart(subId, simState, String.valueOf(carrierName)); if (carrierTextForSimState != null) { @@ -580,7 +557,6 @@ public class CarrierTextManager { return CarrierTextManager.StatusMode.SimLocked; case TelephonyManager.SIM_STATE_PUK_REQUIRED: return CarrierTextManager.StatusMode.SimPukLocked; - case TelephonyManager.SIM_STATE_LOADED: case TelephonyManager.SIM_STATE_READY: return CarrierTextManager.StatusMode.Normal; case TelephonyManager.SIM_STATE_PERM_DISABLED: @@ -681,7 +657,6 @@ public class CarrierTextManager { private boolean mShowAirplaneMode; private boolean mShowMissingSim; private String mDebugLocation; - private CarrierNameCustomization mCarrierNameCustomization; @Inject public Builder( @@ -694,8 +669,7 @@ public class CarrierTextManager { @Main Executor mainExecutor, @Background Executor bgExecutor, KeyguardUpdateMonitor keyguardUpdateMonitor, - CarrierTextManagerLogger logger, - CarrierNameCustomization carrierNameCustomization) { + CarrierTextManagerLogger logger) { mContext = context; mSeparator = resources.getString( com.android.internal.R.string.kg_text_message_separator); @@ -707,7 +681,6 @@ public class CarrierTextManager { mBgExecutor = bgExecutor; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLogger = logger; - mCarrierNameCustomization = carrierNameCustomization; } /** */ @@ -737,7 +710,7 @@ public class CarrierTextManager { return new CarrierTextManager( mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mWifiRepository, mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle, - mMainExecutor, mBgExecutor, mKeyguardUpdateMonitor, mLogger, mCarrierNameCustomization); + mMainExecutor, mBgExecutor, mKeyguardUpdateMonitor, mLogger); } } @@ -798,123 +771,4 @@ public class CarrierTextManager { */ default void finishedWakingUp() {}; } - - private String getCustomizeCarrierName(CharSequence originCarrierName, - SubscriptionInfo sub) { - StringBuilder newCarrierName = new StringBuilder(); - int networkType = getNetworkType(sub.getSubscriptionId()); - String networkClass = networkTypeToString(networkType); - - String fiveGNetworkClass = get5GNetworkClass(sub, networkType); - if ( fiveGNetworkClass != null ) { - networkClass = fiveGNetworkClass; - } - - if (!TextUtils.isEmpty(originCarrierName)) { - String[] names = originCarrierName.toString().split(mSeparator.toString(), 2); - for (int j = 0; j < names.length; j++) { - names[j] = getLocalString( - names[j], com.android.systemui.R.array.origin_carrier_names, - com.android.systemui.R.array.locale_carrier_names); - if (!TextUtils.isEmpty(names[j])) { - if (!TextUtils.isEmpty(networkClass)) { - names[j] = new StringBuilder().append(names[j]).append(" ") - .append(networkClass).toString(); - } - if (j > 0 && names[j].equals(names[j - 1])) { - continue; - } - if (j > 0) { - newCarrierName.append(mSeparator); - } - newCarrierName.append(names[j]); - } - } - } - return newCarrierName.toString(); - } - - /** - * parse the string to current language. - * - * @param originalString original string - * @param originNamesId the id of the original string array. - * @param localNamesId the id of the local string keys. - * @return local language string - */ - private String getLocalString(String originalString, - int originNamesId, int localNamesId) { - String[] origNames = getContext().getResources().getStringArray(originNamesId); - String[] localNames = getContext().getResources().getStringArray(localNamesId); - for (int i = 0; i < origNames.length; i++) { - if (origNames[i].equalsIgnoreCase(originalString)) { - return localNames[i]; - } - } - return originalString; - } - - private int getNetworkType(int subId) { - int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; - ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId); - if (ss != null && (ss.getDataRegState() == ServiceState.STATE_IN_SERVICE - || ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE)) { - networkType = ss.getDataNetworkType(); - if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { - networkType = ss.getVoiceNetworkType(); - } - } - return networkType; - } - - private String networkTypeToString(int networkType) { - int classId = com.android.systemui.R.string.config_rat_unknown; - long mask = TelephonyManager.getBitMaskForNetworkType(networkType); - if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_2G) != 0) { - classId = com.android.systemui.R.string.config_rat_2g; - } else if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_3G) != 0) { - classId = com.android.systemui.R.string.config_rat_3g; - } else if ((mask & TelephonyManager.NETWORK_CLASS_BITMASK_4G) != 0) { - classId = com.android.systemui.R.string.config_rat_4g; - } - return getContext().getResources().getString(classId); - } - - - private String get5GNetworkClass(SubscriptionInfo sub, int networkType) { - if ( networkType == TelephonyManager.NETWORK_TYPE_NR ) { - return mContext.getResources().getString(R.string.data_connection_5g); - } - - int slotIndex = sub.getSimSlotIndex(); - int subId = sub.getSubscriptionId(); - - if ( mFiveGServiceClient == null ) { - mFiveGServiceClient = FiveGServiceClient.getInstance(mContext); - mFiveGServiceClient.registerCallback(mCallback); - } - FiveGServiceState fiveGServiceState = - mFiveGServiceClient.getCurrentServiceState(slotIndex); - if ( fiveGServiceState.isNrIconTypeValid() && isDataRegisteredOnLte(subId)) { - return mContext.getResources().getString(R.string.data_connection_5g); - } - - return null; - } - - private boolean isDataRegisteredOnLte(int subId) { - TelephonyManager telephonyManager = (TelephonyManager) - mContext.getSystemService(Context.TELEPHONY_SERVICE); - int dataType = telephonyManager.getDataNetworkType(subId); - if ( dataType == TelephonyManager.NETWORK_TYPE_LTE || - dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) { - return true; - }else{ - return false; - } - } - - public void loadCarrierMap() { - mCarrierNameCustomization.loadCarrierMap(getContext()); - } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index ca4f2d389703..ae0a639cdfe0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -8,12 +8,14 @@ import static android.view.View.TRANSLATION_Y; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN; import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE; +import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; @@ -128,6 +130,18 @@ public class KeyguardClockSwitch extends RelativeLayout { super(context, attrs); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + if (mDisplayedClockSize != null) { + boolean landscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE; + boolean useLargeClock = mDisplayedClockSize == LARGE && + (!landscape || isLargeScreen(mContext)); + updateClockViews(useLargeClock, /* animate */ true); + } + } + /** * Apply dp changes on configuration change */ @@ -376,11 +390,14 @@ public class KeyguardClockSwitch extends RelativeLayout { if (mDisplayedClockSize != null && clockSize == mDisplayedClockSize) { return false; } + boolean landscape = getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE; + boolean useLargeClock = clockSize == LARGE && (!landscape || isLargeScreen(mContext)); // let's make sure clock is changed only after all views were laid out so we can // translate them properly if (mChildrenAreLaidOut) { - updateClockViews(clockSize == LARGE, animate); + updateClockViews(useLargeClock, animate); } mDisplayedClockSize = clockSize; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bfca5d35156e..336eb82ca62d 100755 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -2480,7 +2480,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Take a guess at initial SIM state, battery status and PLMN until we get an update mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, /* level= */ 100, /* plugged= */ - 0, CHARGING_POLICY_DEFAULT, /* maxChargingWattage= */0, /* present= */true); + 0, CHARGING_POLICY_DEFAULT, /* maxChargingWattage= */0, false, /* present= */true); // Watch for interesting updates final IntentFilter filter = new IntentFilter(); @@ -3926,6 +3926,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return true; } + // change in oem fast charging while plugged in + if (nowPluggedIn && current.oemFastChargeStatus != old.oemFastChargeStatus) { + return true; + } + // change in battery is present or not if (old.present != current.present) { return true; diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java index 8e8ee48aba83..f87ccf51a8ac 100644 --- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java +++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java @@ -30,6 +30,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.PowerManager; import android.os.SystemClock; +import android.provider.Settings; import android.text.InputType; import android.text.TextUtils; import android.util.AttributeSet; @@ -448,7 +449,9 @@ public class PasswordTextView extends FrameLayout { * Controls whether the last entered digit is briefly shown after being entered */ public void setShowPassword(boolean enabled) { - mShowPassword = enabled; + mShowPassword = enabled && + Settings.System.getInt(mContext.getContentResolver(), + Settings.System.TEXT_SHOW_PASSWORD, 1) == 1; } private class CharState { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java index 50e03992df49..9f131446217d 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java @@ -83,7 +83,7 @@ public class SystemUIService extends Service { throw new RuntimeException(); } - if (Build.IS_DEBUGGABLE) { + if (Build.IS_ENG) { // b/71353150 - looking for leaked binder proxies BinderInternal.nSetBinderProxyCountEnabled(true); BinderInternal.nSetBinderProxyCountWatermarks(1000,900); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt index 5ede16d221b7..7731e1108cd4 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.View 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 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at 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/UdfpsSurfaceView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsSurfaceView.java new file mode 100644 index 000000000000..2488132b508b --- /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.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; + } + + 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. + */ + 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. + */ + 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/UdfpsView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt index 06dee7a2b9f6..ef7fcc954590 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt @@ -25,6 +25,7 @@ import android.graphics.RectF import android.util.AttributeSet import android.util.Log import android.view.MotionEvent +import android.view.Surface import android.widget.FrameLayout import com.android.settingslib.udfps.UdfpsOverlayParams import com.android.systemui.R @@ -61,6 +62,8 @@ class UdfpsView( a.getFloat(R.styleable.UdfpsView_sensorTouchAreaCoefficient, 0f) } + private var ghbmView: UdfpsSurfaceView? = null + /** View controller (can be different for enrollment, BiometricPrompt, Keyguard, etc.). */ var animationViewController: UdfpsAnimationViewController<*>? = null @@ -87,6 +90,10 @@ class UdfpsView( return (animationViewController == null || !animationViewController!!.shouldPauseAuth()) } + override fun onFinishInflate() { + ghbmView = findViewById(R.id.hbm_view) + } + override fun dozeTimeTick() { animationViewController?.dozeTimeTick() } @@ -150,12 +157,34 @@ class UdfpsView( fun configureDisplay(onDisplayConfigured: Runnable) { isDisplayConfigured = true animationViewController?.onDisplayConfiguring() - mUdfpsDisplayMode?.enable(onDisplayConfigured) + 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?) { + if (ghbmView != null && surface == null) { + Log.e(TAG, "doIlluminate | surface must be non-null for GHBM") + } + + mUdfpsDisplayMode?.enable { + onDisplayConfigured?.run() + ghbmView?.drawIlluminationDot(RectF(sensorRect)) + } } fun unconfigureDisplay() { isDisplayConfigured = false animationViewController?.onDisplayUnconfigured() + ghbmView?.let { view -> + view.setGhbmIlluminationListener(null) + view.visibility = INVISIBLE + } mUdfpsDisplayMode?.disable(null /* onDisabled */) } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt index 8029ba844850..c4c23124b39e 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt @@ -68,12 +68,6 @@ interface ControlActionCoordinator { fun setValue(cvh: ControlViewHolder, templateId: String, newValue: Float) /** - * Actions may have been put on hold while the device is unlocked. Invoke this action if - * present. - */ - fun runPendingAction(controlId: String) - - /** * User interaction with a control may be blocked for a period of time while actions are being * executed by the application. When the response returns, run this method to enable further * user interaction. diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index 37138114c740..c27a059c20fe 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -64,7 +64,6 @@ class ControlActionCoordinatorImpl @Inject constructor( private val featureFlags: FeatureFlags, ) : ControlActionCoordinator { private var dialog: Dialog? = null - private var pendingAction: Action? = null private var actionsInProgress = mutableSetOf<String>() private val isLocked: Boolean get() = !keyguardStateController.isUnlocked() @@ -166,15 +165,6 @@ class ControlActionCoordinatorImpl @Inject constructor( ) } - override fun runPendingAction(controlId: String) { - if (isLocked) return - if (pendingAction?.controlId == controlId) { - showSettingsDialogIfNeeded(pendingAction!!) - pendingAction?.invoke() - pendingAction = null - } - } - @MainThread override fun enableActionOnTouch(controlId: String) { actionsInProgress.remove(controlId) @@ -196,17 +186,11 @@ class ControlActionCoordinatorImpl @Inject constructor( val authRequired = action.authIsRequired || !allowTrivialControls if (keyguardStateController.isShowing() && authRequired) { - if (isLocked) { - broadcastSender.closeSystemDialogs() - - // pending actions will only run after the control state has been refreshed - pendingAction = action - } activityStarter.dismissKeyguardThenExecute({ Log.d(ControlsUiController.TAG, "Device unlocked, invoking controls action") action.invoke() true - }, { pendingAction = null }, true /* afterKeyguardGone */) + }, null, true /* afterKeyguardGone */) } else { showSettingsDialogIfNeeded(action) action.invoke() diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index c04bc8792223..18fb3e769e84 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -176,8 +176,6 @@ class ControlViewHolder( controlActionCoordinator.longPress(this@ControlViewHolder) true }) - - controlActionCoordinator.runPendingAction(cws.ci.controlId) } val wasLoading = isLoading diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 5bcf32a9ebdb..632d16d4de35 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -54,6 +54,7 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FlagsModule; import com.android.systemui.keyboard.KeyboardModule; import com.android.systemui.keyguard.data.BouncerViewModule; +import com.android.systemui.lineage.LineageModule; import com.android.systemui.log.dagger.LogModule; import com.android.systemui.log.dagger.MonitorLog; import com.android.systemui.log.table.TableLogBuffer; @@ -175,6 +176,7 @@ import javax.inject.Named; GarbageMonitorModule.class, KeyboardModule.class, LetterboxModule.class, + LineageModule.class, LogModule.class, MediaProjectionModule.class, MotionToolModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 07efbfef732b..b8308df20553 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -249,7 +249,7 @@ public class DozeSensors { false /* ignoresSetting */, dozeParameters.longPressUsesProx(), false /* immediatelyReRegister */, - true /* requiresAod */ + !mScreenOffUdfpsEnabled /* requiresAod */ ), new PluginSensor( new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY), diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 85272a609588..bf18b96fb2b6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -326,11 +326,16 @@ public class DozeTriggers implements DozeMachine.Part { mDozeHost.onSlpiTap(screenX, screenY); gentleWakeUp(pulseReason); } else if (isPickup) { + final State state = mMachine.getState(); if (shouldDropPickupEvent()) { mDozeLog.traceSensorEventDropped(pulseReason, "keyguard occluded"); return; } - gentleWakeUp(pulseReason); + if (state == State.DOZE_AOD) { + gentleWakeUp(pulseReason); + } else { + requestPulse(pulseReason, true, null); + } } else if (isUdfpsLongPress) { if (canPulse(mMachine.getState(), true)) { mDozeLog.d("updfsLongPress - setting aodInterruptRunnable to run when " diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 8ef27445fa75..e041202299dc 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -395,7 +395,7 @@ object Flags { val MEDIA_TAP_TO_TRANSFER = releasedFlag(900, "media_tap_to_transfer") // TODO(b/254512502): Tracking Bug - val MEDIA_SESSION_ACTIONS = unreleasedFlag(901, "media_session_actions") + val MEDIA_SESSION_ACTIONS = releasedFlag(901, "media_session_actions") // TODO(b/254512726): Tracking Bug val MEDIA_NEARBY_DEVICES = releasedFlag(903, "media_nearby_devices") diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index b317af0686cb..8ea5e6459bc7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2221,6 +2221,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing && !forceShow) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); + setShowingLocked(false, mAodShowing); + hideLocked(); return; } @@ -3063,7 +3065,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // only play "unlock" noises if not on a call (since the incall UI // disables the keyguard) if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) { - playSounds(false); + if (mShowing && mDeviceInteractive) { + playSounds(false); + } } setShowingLocked(false); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index c44435ee2be0..8bfe951cc93e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -188,6 +188,8 @@ constructor( CameraLaunchSourceModel.LIFT_TRIGGER StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE -> CameraLaunchSourceModel.QUICK_AFFORDANCE + StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE -> + CameraLaunchSourceModel.SCREEN_GESTURE else -> throw IllegalArgumentException("Invalid CameraLaunchSourceModel value: $value") } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt index 19baf7705546..71e0afe09054 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/CameraLaunchSourceModel.kt @@ -25,4 +25,6 @@ enum class CameraLaunchSourceModel { LIFT_TRIGGER, /** Quick affordance button has been pressed */ QUICK_AFFORDANCE, + /** Screen gesture has been triggered */ + SCREEN_GESTURE, } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt index e7803c5e964c..29fc70167ebb 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.ui.binder import android.os.VibrationEffect +import com.android.systemui.statusbar.VibratorHelper import kotlin.time.Duration.Companion.milliseconds object KeyguardBottomAreaVibrations { @@ -27,6 +28,14 @@ object KeyguardBottomAreaVibrations { private const val SmallVibrationScale = 0.3f private const val BigVibrationScale = 0.6f + val vibratorHelper: VibratorHelper? = null + val areAllPrimitivesSupported = vibratorHelper?.areAllPrimitivesSupported( + VibrationEffect.Composition.PRIMITIVE_TICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, + VibrationEffect.Composition.PRIMITIVE_QUICK_FALL + ) ?: false + + val ShakeAlt = VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK) val Shake = VibrationEffect.startComposition() .apply { @@ -45,6 +54,7 @@ object KeyguardBottomAreaVibrations { } .compose() + val ActivatedAlt = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK) val Activated = VibrationEffect.startComposition() .addPrimitive( @@ -59,6 +69,7 @@ object KeyguardBottomAreaVibrations { ) .compose() + val DeactivatedAlt = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK) val Deactivated = VibrationEffect.startComposition() .addPrimitive( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt index b64fc33ea252..eafcac50764e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaViewBinder.kt @@ -279,7 +279,12 @@ object KeyguardBottomAreaViewBinder { isVisible -> settingsMenu.animateVisibility(visible = isVisible) if (isVisible) { - vibratorHelper?.vibrate(KeyguardBottomAreaVibrations.Activated) + vibratorHelper?.vibrate( + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Activated + } else { + KeyguardBottomAreaVibrations.ActivatedAlt + }) settingsMenu.setOnTouchListener( KeyguardSettingsButtonOnTouchListener( view = settingsMenu, @@ -491,9 +496,17 @@ object KeyguardBottomAreaViewBinder { ) vibratorHelper?.vibrate( if (viewModel.isActivated) { - KeyguardBottomAreaVibrations.Activated + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Activated + } else { + KeyguardBottomAreaVibrations.ActivatedAlt + } } else { - KeyguardBottomAreaVibrations.Deactivated + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Deactivated + } else { + KeyguardBottomAreaVibrations.DeactivatedAlt + } } ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt index 7685345805f4..ec7883ac5e20 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceOnTouchListener.kt @@ -128,7 +128,12 @@ class KeyguardQuickAffordanceOnTouchListener( ) shakeAnimator.start() - vibratorHelper?.vibrate(KeyguardBottomAreaVibrations.Shake) + vibratorHelper?.vibrate( + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Shake + } else { + KeyguardBottomAreaVibrations.ShakeAlt + }) } } else { null @@ -151,9 +156,17 @@ class KeyguardQuickAffordanceOnTouchListener( view.setOnClickListener { vibratorHelper?.vibrate( if (viewModel.isActivated) { - KeyguardBottomAreaVibrations.Activated + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Activated + } else { + KeyguardBottomAreaVibrations.ActivatedAlt + } } else { - KeyguardBottomAreaVibrations.Deactivated + if (KeyguardBottomAreaVibrations.areAllPrimitivesSupported) { + KeyguardBottomAreaVibrations.Deactivated + } else { + KeyguardBottomAreaVibrations.DeactivatedAlt + } } ) viewModel.onClicked( diff --git a/packages/SystemUI/src/com/android/systemui/lineage/LineageModule.kt b/packages/SystemUI/src/com/android/systemui/lineage/LineageModule.kt new file mode 100644 index 000000000000..3e9aec36d8f3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/lineage/LineageModule.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2023 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.lineage + +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.qs.tiles.AODTile +import com.android.systemui.qs.tiles.CaffeineTile +import com.android.systemui.qs.tiles.HeadsUpTile + +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +interface LineageModule { + /** Inject AODTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(AODTile.TILE_SPEC) + fun bindAODTile(aodTile: AODTile): QSTileImpl<*> + + /** Inject CaffeineTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(CaffeineTile.TILE_SPEC) + fun bindCaffeineTile(caffeineTile: CaffeineTile): QSTileImpl<*> + + /** Inject HeadsUpTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(HeadsUpTile.TILE_SPEC) + fun bindHeadsUpTile(headsUpTile: HeadsUpTile): QSTileImpl<*> +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java index 2a7704f13c3b..154bc79dbe6a 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java @@ -18,11 +18,17 @@ package com.android.systemui.navigationbar; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Context; +import android.content.om.IOverlayManager; import android.content.res.Configuration; import android.graphics.drawable.Icon; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -43,12 +49,13 @@ import com.android.systemui.navigationbar.buttons.ReverseLinearLayout; import com.android.systemui.navigationbar.buttons.ReverseLinearLayout.ReverseRelativeLayout; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.tuner.TunerService; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.Objects; -public class NavigationBarInflaterView extends FrameLayout { +public class NavigationBarInflaterView extends FrameLayout implements TunerService.Tunable { private static final String TAG = "NavBarInflater"; public static final String NAV_BAR_VIEWS = "sysui_nav_bar"; @@ -82,6 +89,11 @@ public class NavigationBarInflaterView extends FrameLayout { private static final String ABSOLUTE_SUFFIX = "A"; private static final String ABSOLUTE_VERTICAL_CENTERED_SUFFIX = "C"; + private static final String KEY_NAVIGATION_HINT = + Settings.Secure.NAVIGATION_BAR_HINT; + private static final String OVERLAY_NAVIGATION_HIDE_HINT = + "android.ice.overlay.hidenav"; + private static class Listener implements NavigationModeController.ModeChangedListener { private final WeakReference<NavigationBarInflaterView> mSelf; @@ -119,6 +131,8 @@ public class NavigationBarInflaterView extends FrameLayout { private OverviewProxyService mOverviewProxyService; private int mNavBarMode = NAV_BAR_MODE_3BUTTON; + private boolean mIsHintEnabled; + public NavigationBarInflaterView(Context context, AttributeSet attrs) { super(context, attrs); createInflaters(); @@ -161,11 +175,21 @@ public class NavigationBarInflaterView extends FrameLayout { : mOverviewProxyService.shouldShowSwipeUpUI() ? R.string.config_navBarLayoutQuickstep : R.string.config_navBarLayout; + if (!mIsHintEnabled && defaultResource == R.string.config_navBarLayoutHandle) { + return getContext().getString(defaultResource).replace(HOME_HANDLE, ""); + } return getContext().getString(defaultResource); } private void onNavigationModeChanged(int mode) { mNavBarMode = mode; + updateHint(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + Dependency.get(TunerService.class).addTunable(this, KEY_NAVIGATION_HINT); } @Override @@ -174,6 +198,15 @@ public class NavigationBarInflaterView extends FrameLayout { super.onDetachedFromWindow(); } + @Override + public void onTuningChanged(String key, String newValue) { + if (KEY_NAVIGATION_HINT.equals(key)) { + mIsHintEnabled = TunerService.parseIntegerSwitch(newValue, true); + updateHint(); + onLikelyDefaultLayoutChange(); + } + } + public void onLikelyDefaultLayoutChange() { // Reevaluate new layout final String newValue = getDefaultLayout(); @@ -227,6 +260,24 @@ public class NavigationBarInflaterView extends FrameLayout { } } + private void updateHint() { + final IOverlayManager iom = IOverlayManager.Stub.asInterface( + ServiceManager.getService(Context.OVERLAY_SERVICE)); + final boolean state = mNavBarMode == NAV_BAR_MODE_GESTURAL && !mIsHintEnabled; + final int userId = ActivityManager.getCurrentUser(); + try { + iom.setEnabled(OVERLAY_NAVIGATION_HIDE_HINT, state, userId); + if (state) { + // As overlays are also used to apply navigation mode, it is needed to set + // our customization overlay to highest priority to ensure it is applied. + iom.setHighestPriority(OVERLAY_NAVIGATION_HIDE_HINT, userId); + } + } catch (IllegalArgumentException | RemoteException e) { + Log.e(TAG, "Failed to " + (state ? "enable" : "disable") + + " overlay " + OVERLAY_NAVIGATION_HIDE_HINT + " for user " + userId); + } + } + private void initiallyFill(ButtonDispatcher buttonDispatcher) { addAll(buttonDispatcher, mHorizontal.findViewById(R.id.ends_group)); addAll(buttonDispatcher, mHorizontal.findViewById(R.id.center_group)); diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt index d652889f0082..3f5e5223e91e 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt @@ -28,7 +28,6 @@ import com.android.systemui.util.asIndenting import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.withIncreasedIndent import java.io.PrintWriter -import java.lang.ref.WeakReference import javax.inject.Inject @SysUISingleton @@ -50,7 +49,7 @@ class PrivacyConfig @Inject constructor( private const val DEFAULT_MEDIA_PROJECTION = true } - private val callbacks = mutableListOf<WeakReference<Callback>>() + private val callbacks = mutableListOf<Callback>() var micCameraAvailable = isMicCameraEnabled() private set @@ -65,19 +64,19 @@ class PrivacyConfig @Inject constructor( // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(MIC_CAMERA)) { micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA) - callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } + callbacks.forEach { it.onFlagMicCameraChanged(micCameraAvailable) } } if (properties.keyset.contains(LOCATION)) { locationAvailable = properties.getBoolean(LOCATION, DEFAULT_LOCATION) - callbacks.forEach { it.get()?.onFlagLocationChanged(locationAvailable) } + callbacks.forEach { it.onFlagLocationChanged(locationAvailable) } } if (properties.keyset.contains(MEDIA_PROJECTION)) { mediaProjectionAvailable = properties.getBoolean(MEDIA_PROJECTION, DEFAULT_MEDIA_PROJECTION) callbacks.forEach { - it.get()?.onFlagMediaProjectionChanged(mediaProjectionAvailable) + it.onFlagMediaProjectionChanged(mediaProjectionAvailable) } } } @@ -107,23 +106,14 @@ class PrivacyConfig @Inject constructor( } fun addCallback(callback: Callback) { - addCallback(WeakReference(callback)) - } - - fun removeCallback(callback: Callback) { - removeCallback(WeakReference(callback)) - } - - private fun addCallback(callback: WeakReference<Callback>) { uiExecutor.execute { callbacks.add(callback) } } - private fun removeCallback(callback: WeakReference<Callback>) { + fun removeCallback(callback: Callback) { uiExecutor.execute { - // Removes also if the callback is null - callbacks.removeIf { it.get()?.equals(callback.get()) ?: true } + callbacks.remove(callback) } } @@ -136,9 +126,7 @@ class PrivacyConfig @Inject constructor( ipw.println("mediaProjectionAvailable: $mediaProjectionAvailable") ipw.println("Callbacks:") ipw.withIncreasedIndent { - callbacks.forEach { callback -> - callback.get()?.let { ipw.println(it) } - } + callbacks.forEach { ipw.println(it) } } } ipw.flush() @@ -154,4 +142,4 @@ class PrivacyConfig @Inject constructor( @JvmDefault fun onFlagMediaProjectionChanged(flag: Boolean) {} } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java index fa3f878ff431..032f8776a597 100644 --- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java +++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java @@ -345,8 +345,6 @@ public class QRCodeScannerController implements // Reset cached values to default as we are no longer listening mQRCodeScannerPreferenceObserver = new HashMap<>(); - mSecureSettings.putStringForUser(Settings.Secure.SHOW_QR_CODE_SCANNER_SETTING, null, - mUserTracker.getUserId()); } private void unregisterDefaultQRCodeScannerObserver() { @@ -358,6 +356,8 @@ public class QRCodeScannerController implements mQRCodeScannerActivity = null; mIntent = null; mComponentName = null; + mSecureSettings.putStringForUser(Settings.Secure.SHOW_QR_CODE_SCANNER_SETTING, null, + mUserTracker.getUserId()); } private void notifyQRCodeScannerActivityChanged() { @@ -385,7 +385,10 @@ public class QRCodeScannerController implements // While registering the observers for the first time update the default values in the // background - mExecutor.execute(() -> updateQRCodeScannerActivityDetails()); + mExecutor.execute(() -> { + updateQRCodeScannerActivityDetails(); + updateQRCodeScannerPreferenceDetails(/* updateSettings = */true); + }); mOnDefaultQRCodeScannerChangedListener = properties -> { if (DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace()) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java index 856c64a52290..c03eaf4daf69 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java @@ -46,7 +46,7 @@ public interface QSHost { final String defaultTileList = res.getString(R.string.quick_settings_tiles_default); tiles.addAll(Arrays.asList(defaultTileList.split(","))); - if (Build.IS_DEBUGGABLE + if (Build.IS_ENG && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) { tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index d511d8aea019..7ef47ab2293a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -93,12 +93,8 @@ public class QSCustomizer extends LinearLayout { } void updateNavBackDrop(Configuration newConfig, LightBarController lightBarController) { - View navBackdrop = findViewById(R.id.nav_bar_background); mIsShowingNavBackdrop = newConfig.smallestScreenWidthDp >= 600 || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE; - if (navBackdrop != null) { - navBackdrop.setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE); - } updateNavColors(lightBarController); } 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 596475eedb43..7f0011b0a4c3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -23,9 +23,11 @@ import android.graphics.Rect; 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; @@ -342,7 +344,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta 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 { @@ -423,6 +425,18 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta 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 d9f448493591..82f9f921af42 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -114,7 +114,7 @@ public class TileQueryHelper { possibleTiles.add(spec); } } - if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) { + if (Build.IS_ENG && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) { possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index 6b23f5d77145..97f481325e58 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -81,8 +81,8 @@ public class QSFactoryImpl implements QSFactory { protected QSTileImpl createTileInternal(String tileSpec) { // Stock tiles. if (mTileMap.containsKey(tileSpec) - // We should not return a Garbage Monitory Tile if the build is not Debuggable - && (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_DEBUGGABLE)) { + // We should not return a Garbage Monitory Tile if the build is not Eng + && (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_ENG)) { return mTileMap.get(tileSpec).get(); } 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 000000000000..27edb0e2ad55 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AODTile.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2018 The OmniROM Project + * 2020-2021 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.Intent; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.service.quicksettings.Tile; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.R; +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.SettingObserver; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.util.settings.SecureSettings; + +import javax.inject.Inject; + +public class AODTile extends QSTileImpl<BooleanState> implements + BatteryController.BatteryStateChangeCallback { + + public static final String TILE_SPEC = "aod"; + + private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_aod); + private final BatteryController mBatteryController; + + private final SettingObserver 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 SettingObserver(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 + protected void handleClick(@Nullable View view) { + mSetting.setValue(mState.value ? 0 : 1); + } + + @Override + public Intent getLongClickIntent() { + return null; + } + + @Override + public CharSequence getTileLabel() { + if (mBatteryController.isAodPowerSave()) { + return mContext.getString(R.string.quick_settings_aod_off_powersave_label); + } + 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; + if (state.slash == null) { + state.slash = new SlashState(); + } + state.icon = mIcon; + state.value = enable; + state.slash.isSlashed = state.value; + state.label = mContext.getString(R.string.quick_settings_aod_label); + if (mBatteryController.isAodPowerSave()) { + state.state = Tile.STATE_UNAVAILABLE; + } else { + state.state = enable ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; + } + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.ICE; + } +} 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 000000000000..a4a6c1738530 --- /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 android.view.View; + +import androidx.annotation.Nullable; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.R; +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 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 View view) { + // 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 View view) { + 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.ICE; + } + + 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 cb6dbff00e3b..3ef3e1284c16 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -116,7 +116,6 @@ public class CastTile extends QSTileImpl<BooleanState> { @Override public BooleanState newTileState() { BooleanState state = new BooleanState(); - state.handlesLongClick = false; return state; } @@ -137,12 +136,7 @@ public class CastTile extends QSTileImpl<BooleanState> { @Override public Intent getLongClickIntent() { - return new Intent(Settings.ACTION_CAST_SETTINGS); - } - - @Override - protected void handleLongClick(@Nullable View view) { - handleClick(view); + return CAST_SETTINGS; } @Override @@ -305,7 +299,8 @@ public class CastTile extends QSTileImpl<BooleanState> { refreshState(); } } else { - boolean enabledAndConnected = indicators.enabled && indicators.qsIcon.visible; + boolean enabledAndConnected = indicators.enabled + && (indicators.qsIcon == null ? false : indicators.qsIcon.visible); if (enabledAndConnected != mWifiConnected) { mWifiConnected = enabledAndConnected; // Hotspot is not connected, so changes here should update diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java new file mode 100644 index 000000000000..f75e84664cbd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java @@ -0,0 +1,141 @@ +/* + * 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. + */ + +package com.android.systemui.qs.tiles; + +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.service.quicksettings.Tile; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.R; +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.SettingObserver; +import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.settings.UserTracker; +import com.android.systemui.util.settings.GlobalSettings; + +import javax.inject.Inject; + +/** Quick settings tile: Heads up **/ +public class HeadsUpTile extends QSTileImpl<BooleanState> { + + public static final String TILE_SPEC = "heads_up"; + + private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_heads_up); + + private static final Intent NOTIFICATION_SETTINGS = + new Intent("android.settings.NOTIFICATION_SETTINGS"); + + private final SettingObserver mSetting; + + @Inject + public HeadsUpTile( + QSHost host, + QsEventLogger uiEventLogger, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + FalsingManager falsingManager, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger, + GlobalSettings globalSettings, + UserTracker userTracker + ) { + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, + statusBarStateController, activityStarter, qsLogger); + + mSetting = new SettingObserver(globalSettings, mHandler, + Global.HEADS_UP_NOTIFICATIONS_ENABLED, userTracker.getUserId()) { + @Override + protected void handleValueChanged(int value, boolean observedChange) { + handleRefreshState(value); + } + }; + } + + @Override + public BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleClick(@Nullable View view) { + setEnabled(!mState.value); + refreshState(); + } + + @Override + public Intent getLongClickIntent() { + return NOTIFICATION_SETTINGS; + } + + private void setEnabled(boolean enabled) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, + enabled ? 1 : 0); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue(); + final boolean headsUp = value != 0; + state.value = headsUp; + state.label = mContext.getString(R.string.quick_settings_heads_up_label); + state.icon = mIcon; + if (headsUp) { + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_on); + state.state = Tile.STATE_ACTIVE; + } else { + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_off); + state.state = Tile.STATE_INACTIVE; + } + } + + @Override + public CharSequence getTileLabel() { + return mContext.getString(R.string.quick_settings_heads_up_label); + } + + @Override + public int getMetricsCategory() { + return MetricsEvent.ICE; + } + + @Override + public void handleSetListening(boolean listening) { + // Do nothing + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 04baa94dc54e..b6d0e1b1ce6e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -68,7 +68,6 @@ import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.connectivity.WifiIcons; import com.android.systemui.statusbar.connectivity.WifiIndicators; -import com.android.systemui.util.CarrierNameCustomization; import java.io.PrintWriter; @@ -94,7 +93,6 @@ public class InternetTile extends QSTileImpl<SignalState> { protected final InternetSignalCallback mSignalCallback = new InternetSignalCallback(); private final InternetDialogFactory mInternetDialogFactory; final Handler mHandler; - private CarrierNameCustomization mCarrierNameCustomization; @Inject public InternetTile( @@ -109,8 +107,7 @@ public class InternetTile extends QSTileImpl<SignalState> { QSLogger qsLogger, NetworkController networkController, AccessPointController accessPointController, - InternetDialogFactory internetDialogFactory, - CarrierNameCustomization carrierNameCustomization + InternetDialogFactory internetDialogFactory ) { super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); @@ -120,7 +117,6 @@ public class InternetTile extends QSTileImpl<SignalState> { mAccessPointController = accessPointController; mDataController = mController.getMobileDataController(); mController.observe(getLifecycle(), mSignalCallback); - mCarrierNameCustomization = carrierNameCustomization; } @Override @@ -350,14 +346,8 @@ public class InternetTile extends QSTileImpl<SignalState> { return; } synchronized (mCellularInfo) { - if (mCarrierNameCustomization.isRoamingCustomizationEnabled() - && mCarrierNameCustomization.isRoaming(indicators.subId)) { - mCellularInfo.mDataSubscriptionName = - mCarrierNameCustomization.getRoamingCarrierName(indicators.subId); - } else { - mCellularInfo.mDataSubscriptionName = indicators.qsDescription == null - ? mController.getMobileDataNetworkName() : indicators.qsDescription; - } + mCellularInfo.mDataSubscriptionName = indicators.qsDescription == null + ? mController.getMobileDataNetworkName() : indicators.qsDescription; mCellularInfo.mDataContentDescription = indicators.qsDescription != null ? indicators.typeContentDescriptionHtml : null; mCellularInfo.mMobileSignalIconId = indicators.qsIcon.icon; 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 29ccb76de820..7baf40d01206 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -89,6 +89,7 @@ public class NfcTile extends QSTileImpl<BooleanState> { @Override public void handleSetListening(boolean listening) { super.handleSetListening(listening); + if (mListening == listening) return; mListening = listening; if (mListening) { mBroadcastDispatcher.registerReceiver(mNfcReceiver, @@ -155,7 +156,7 @@ public class NfcTile extends QSTileImpl<BooleanState> { private NfcAdapter getAdapter() { if (mAdapter == null) { try { - mAdapter = NfcAdapter.getDefaultAdapter(mContext); + mAdapter = NfcAdapter.getNfcAdapter(mContext.getApplicationContext()); } catch (UnsupportedOperationException e) { mAdapter = null; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 8bed9c53465c..0ae53b8fbc65 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -339,6 +339,7 @@ public class InternetDialog extends SystemUIDialog implements mHandler.removeCallbacks(mHideProgressBarRunnable); mHandler.removeCallbacks(mHideSearchingRunnable); mMobileNetworkLayout.setOnClickListener(null); + mMobileNetworkLayout.setOnLongClickListener(null); mMobileDataToggle.setOnCheckedChangeListener(null); mConnectedWifListLayout.setOnClickListener(null); if (mSecondaryMobileNetworkLayout != null) { @@ -411,6 +412,13 @@ public class InternetDialog extends SystemUIDialog implements } mInternetDialogController.connectCarrierNetwork(); }); + mMobileNetworkLayout.setOnLongClickListener(v -> { + if (!mInternetDialogController.isDeviceLocked()) { + mInternetDialogController.launchMobileNetworkSettings(v, mDefaultDataSubId); + return true; + } + return false; + }); mMobileDataToggle.setOnCheckedChangeListener( (buttonView, isChecked) -> { if (!isChecked && shouldShowMobileDialog(mDefaultDataSubId)) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index f519e611328a..125a91e8a74d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -98,7 +98,6 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.toast.SystemUIToast; import com.android.systemui.toast.ToastFactory; import com.android.systemui.util.CarrierConfigTracker; -import com.android.systemui.util.CarrierNameCustomization; import com.android.systemui.util.settings.GlobalSettings; import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; @@ -229,7 +228,6 @@ public class InternetDialogController implements AccessPointController.AccessPoi protected ConnectedWifiInternetMonitor mConnectedWifiInternetMonitor; @VisibleForTesting protected boolean mCarrierNetworkChangeMode; - private CarrierNameCustomization mCarrierNameCustomization; private boolean mIsSmartDdsSwitchFeatureAvailable; private boolean mIsExtTelServiceConnected = false; @@ -296,8 +294,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi LocationController locationController, DialogLaunchAnimator dialogLaunchAnimator, WifiStateWorker wifiStateWorker, - FeatureFlags featureFlags, - CarrierNameCustomization carrierNameCustomization + FeatureFlags featureFlags ) { if (DEBUG) { Log.d(TAG, "Init InternetDialogController"); @@ -332,7 +329,6 @@ public class InternetDialogController implements AccessPointController.AccessPoi mConnectedWifiInternetMonitor = new ConnectedWifiInternetMonitor(); mWifiStateWorker = wifiStateWorker; mFeatureFlags = featureFlags; - mCarrierNameCustomization = carrierNameCustomization; mExtTelephonyManager = ExtTelephonyManager.getInstance(context); } @@ -725,12 +721,7 @@ public class InternetDialogController implements AccessPointController.AccessPoi } CharSequence getMobileNetworkTitle(int subId) { - if (mCarrierNameCustomization.isRoamingCustomizationEnabled() - && mCarrierNameCustomization.isRoaming(subId)) { - return mCarrierNameCustomization.getRoamingCarrierName(subId); - } else { - return getUniqueSubscriptionDisplayName(subId, mContext); - } + return getUniqueSubscriptionDisplayName(subId, mContext); } String getMobileNetworkSummary(int subId) { @@ -821,6 +812,10 @@ public class InternetDialogController implements AccessPointController.AccessPoi void launchMobileNetworkSettings(View view) { final int subId = getActiveAutoSwitchNonDdsSubId(); + launchMobileNetworkSettings(view, subId); + } + + void launchMobileNetworkSettings(View view, int subId) { if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { Log.w(TAG, "launchMobileNetworkSettings fail, invalid subId:" + subId); return; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java index 5ad16f0a6078..16581ae630ea 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java @@ -391,19 +391,8 @@ public class ImageExporter { static void updateExifAttributes(ExifInterface exif, UUID uniqueId, int width, int height, ZonedDateTime captureTime) { - exif.setAttribute(ExifInterface.TAG_IMAGE_UNIQUE_ID, uniqueId.toString()); - - exif.setAttribute(ExifInterface.TAG_SOFTWARE, "Android " + Build.DISPLAY); exif.setAttribute(ExifInterface.TAG_IMAGE_WIDTH, Integer.toString(width)); exif.setAttribute(ExifInterface.TAG_IMAGE_LENGTH, Integer.toString(height)); - - String dateTime = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss").format(captureTime); - String subSec = DateTimeFormatter.ofPattern("SSS").format(captureTime); - String timeZone = DateTimeFormatter.ofPattern("xxx").format(captureTime); - - exif.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, dateTime); - exif.setAttribute(ExifInterface.TAG_SUBSEC_TIME_ORIGINAL, subSec); - exif.setAttribute(ExifInterface.TAG_OFFSET_TIME_ORIGINAL, timeZone); } static String getMimeType(CompressFormat format) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index b59106efb769..bf61cfb11cc1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -54,6 +54,7 @@ import android.graphics.Insets; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.media.AudioAttributes; +import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaPlayer; import android.net.Uri; @@ -62,6 +63,8 @@ import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.os.VibrationEffect; +import android.os.Vibrator; import android.provider.Settings; import android.util.DisplayMetrics; import android.util.Log; @@ -255,7 +258,7 @@ public class ScreenshotController { // From WizardManagerHelper.java private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete"; - private static final int SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS = 6000; + private static final int SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS = 3000; private final WindowContext mContext; private final FeatureFlags mFlags; @@ -271,6 +274,7 @@ public class ScreenshotController { private final WindowManager mWindowManager; private final WindowManager.LayoutParams mWindowLayoutParams; private final AccessibilityManager mAccessibilityManager; + private final AudioManager mAudioManager; private final ListenableFuture<MediaPlayer> mCameraSound; private final ScrollCaptureClient mScrollCaptureClient; private final PhoneWindow mWindow; @@ -278,6 +282,7 @@ public class ScreenshotController { private final DisplayTracker mDisplayTracker; private final ScrollCaptureController mScrollCaptureController; private final LongScreenshotData mLongScreenshotHolder; + private final Vibrator mVibrator; private final boolean mIsLowRamDevice; private final ScreenshotNotificationSmartActionsProvider mScreenshotNotificationSmartActionsProvider; @@ -386,6 +391,10 @@ public class ScreenshotController { // Setup the Camera shutter sound mCameraSound = loadCameraSound(); + // Grab system services needed for screenshot sound + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + mCopyBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -911,12 +920,21 @@ public class ScreenshotController { private void playCameraSound() { mCameraSound.addListener(() -> { - try { - MediaPlayer player = mCameraSound.get(); - if (player != null) { - player.start(); - } - } catch (InterruptedException | ExecutionException e) { + switch (mAudioManager.getRingerMode()) { + case AudioManager.RINGER_MODE_NORMAL: + // Play the shutter sound to notify that we've taken a screenshot + try { + MediaPlayer player = mCameraSound.get(); + if (player != null) { + player.start(); + } + } catch (InterruptedException | ExecutionException e) { + } + case AudioManager.RINGER_MODE_VIBRATE: + if (mVibrator != null && mVibrator.hasVibrator()) { + mVibrator.vibrate(VibrationEffect.createOneShot(50, + VibrationEffect.DEFAULT_AMPLITUDE)); + } } }, mBgExecutor); } diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index 093c09fff995..b66da98f8f06 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -120,8 +120,8 @@ public class ScreenshotView extends FrameLayout implements private static final long SCREENSHOT_TO_CORNER_X_DURATION_MS = 234; private static final long SCREENSHOT_TO_CORNER_Y_DURATION_MS = 500; private static final long SCREENSHOT_TO_CORNER_SCALE_DURATION_MS = 234; - public static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 400; - private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 100; + public static final long SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS = 300; + private static final long SCREENSHOT_ACTIONS_ALPHA_DURATION_MS = 75; private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f; private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 335aeda766aa..9867ecbee2af 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -70,6 +70,7 @@ import android.provider.Settings; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.MathUtils; +import android.view.GestureDetector; import android.view.InputDevice; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -217,6 +218,7 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.window.StatusBarWindowStateController; +import com.android.systemui.tuner.TunerService; import com.android.systemui.unfold.SysUIUnfoldComponent; import com.android.systemui.util.Compile; import com.android.systemui.util.LargeScreenUtils; @@ -273,6 +275,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump private static final String COUNTER_PANEL_OPEN = "panel_open"; public static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs"; private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek"; + private static final String DOUBLE_TAP_SLEEP_GESTURE = + Settings.Secure.DOUBLE_TAP_SLEEP_GESTURE; private static final Rect M_DUMMY_DIRTY_RECT = new Rect(0, 0, 1, 1); private static final Rect EMPTY_RECT = new Rect(); /** @@ -351,6 +355,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump private final QuickSettingsController mQsController; private final InteractionJankMonitor mInteractionJankMonitor; private final TouchHandler mTouchHandler = new TouchHandler(); + private final TunerService mTunerService; private long mDownTime; private boolean mTouchSlopExceededBeforeDown; @@ -503,6 +508,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump private final NotificationShadeDepthController mDepthController; private final NavigationBarController mNavigationBarController; private final int mDisplayId; + private boolean mDoubleTapToSleepEnabled; + private GestureDetector mDoubleTapGesture; private final KeyguardIndicationController mKeyguardIndicationController; private int mHeadsUpInset; @@ -748,7 +755,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump KeyguardInteractor keyguardInteractor, ActivityStarter activityStarter, EmergencyButtonController.Factory emergencyButtonControllerFactory, - KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) { + KeyguardFaceAuthInteractor keyguardFaceAuthInteractor, + TunerService tunerService) { mInteractionJankMonitor = interactionJankMonitor; keyguardStateController.addCallback(new KeyguardStateController.Callback() { @Override @@ -843,6 +851,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump LargeScreenUtils.shouldUseSplitNotificationShade(mResources); mView.setWillNotDraw(!DEBUG_DRAWABLE); mShadeHeaderController = shadeHeaderController; + mTunerService = tunerService; mLayoutInflater = layoutInflater; mFeatureFlags = featureFlags; mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE); @@ -887,6 +896,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump }); mBottomAreaShadeAlphaAnimator.setDuration(160); mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT); + mDoubleTapGesture = new GestureDetector(mView.getContext(), + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onDoubleTap(MotionEvent e) { + if (mPowerManager != null) { + mPowerManager.goToSleep(e.getEventTime()); + } + return true; + } + }); mConversationNotificationManager = conversationNotificationManager; mAuthController = authController; mLockIconViewController = lockIconViewController; @@ -4445,7 +4464,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump positionClockAndNotifications(true /* forceUpdate */); } - private final class ShadeAttachStateChangeListener implements View.OnAttachStateChangeListener { + private final class ShadeAttachStateChangeListener implements View.OnAttachStateChangeListener, + TunerService.Tunable { @Override public void onViewAttachedToWindow(View v) { mFragmentService.getFragmentHostManager(mView) @@ -4453,6 +4473,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump mStatusBarStateController.addCallback(mStatusBarStateListener); mStatusBarStateListener.onStateChanged(mStatusBarStateController.getState()); mConfigurationController.addCallback(mConfigurationListener); + mTunerService.addTunable(this, DOUBLE_TAP_SLEEP_GESTURE); // Theme might have changed between inflating this view and attaching it to the // window, so // force a call to onThemeChanged @@ -4469,8 +4490,16 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump .removeTagListener(QS.TAG, mQsController.getQsFragmentListener()); mStatusBarStateController.removeCallback(mStatusBarStateListener); mConfigurationController.removeCallback(mConfigurationListener); + mTunerService.removeTunable(this); mFalsingManager.removeTapListener(mFalsingTapListener); } + + @Override + public void onTuningChanged(String key, String newValue) { + if (DOUBLE_TAP_SLEEP_GESTURE.equals(key)) { + mDoubleTapToSleepEnabled = TunerService.parseIntegerSwitch(newValue, true); + } + } } private final class ShadeLayoutChangeListener implements View.OnLayoutChangeListener { @@ -4799,6 +4828,10 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump return false; } + if (mDoubleTapToSleepEnabled && !mPulsing && !mDozing && mBarState == StatusBarState.KEYGUARD) { + mDoubleTapGesture.onTouchEvent(event); + } + // Make sure the next touch won't the blocked after the current ends. if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt index fd82e2fc01fc..702302d5d1ea 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt @@ -60,10 +60,13 @@ class PulsingGestureListener @Inject constructor( ) : GestureDetector.SimpleOnGestureListener(), Dumpable { private var doubleTapEnabled = false private var singleTapEnabled = false + private var doubleTapEnabledNative = false init { - val tunable = Tunable { key: String?, _: String? -> + val tunable = Tunable { key: String?, value: String? -> when (key) { + Settings.Secure.DOUBLE_TAP_TO_WAKE -> + doubleTapEnabledNative = TunerService.parseIntegerSwitch(value, false) Settings.Secure.DOZE_DOUBLE_TAP_GESTURE -> doubleTapEnabled = ambientDisplayConfiguration.doubleTapGestureEnabled( userTracker.userId) @@ -73,6 +76,7 @@ class PulsingGestureListener @Inject constructor( } } tunerService.addTunable(tunable, + Settings.Secure.DOUBLE_TAP_TO_WAKE, Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, Settings.Secure.DOZE_TAP_SCREEN_GESTURE) @@ -109,7 +113,7 @@ class PulsingGestureListener @Inject constructor( // checks MUST be on the ACTION_UP event. if (e.actionMasked == MotionEvent.ACTION_UP && statusBarStateController.isDozing && - (doubleTapEnabled || singleTapEnabled) && + (doubleTapEnabled || singleTapEnabled || doubleTapEnabledNative) && !falsingManager.isProximityNear && !falsingManager.isFalseDoubleTap ) { @@ -126,6 +130,7 @@ class PulsingGestureListener @Inject constructor( override fun dump(pw: PrintWriter, args: Array<out String>) { pw.println("singleTapEnabled=$singleTapEnabled") pw.println("doubleTapEnabled=$doubleTapEnabled") + pw.println("doubleTapEnabledNative=$doubleTapEnabledNative") pw.println("isDocked=${dockManager.isDocked}") pw.println("isProxCovered=${falsingManager.isProximityNear}") } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt index 3af75cef3d4c..f132dd95ce4a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt @@ -304,6 +304,11 @@ constructor( 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/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java index 324e97294f4e..38219bed09c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java @@ -124,6 +124,14 @@ public class VibratorHelper { } /** + * @see Vibrator#areAllPrimitivesSupported(VibrationEffect.Composition.PrimitiveType int...) + */ + public boolean areAllPrimitivesSupported( + @NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) { + return mVibrator != null && mVibrator.areAllPrimitivesSupported(primitiveIds); + } + + /** * @see Vibrator#cancel() */ public void cancel() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index 89e9acef8da4..1b36dd55a7a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -65,9 +65,6 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy; -import com.android.systemui.statusbar.policy.FiveGServiceClient; -import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState; -import com.android.systemui.statusbar.policy.FiveGServiceClient.IFiveGStateListener; import com.android.systemui.util.CarrierConfigTracker; import java.io.PrintWriter; @@ -108,14 +105,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile private int mCallState = TelephonyManager.CALL_STATE_IDLE; - /****************************SideCar****************************/ - @VisibleForTesting - FiveGStateListener mFiveGStateListener; - @VisibleForTesting - FiveGServiceState mFiveGState; - private FiveGServiceClient mClient; - /**********************************************************/ - private ConnectivityManager mConnectivityManager; private ConnectivityManager.NetworkCallback mNetworkCallback; private boolean mIsConnectionFailed = false; @@ -175,8 +164,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile mDefaults = defaults; mSubscriptionInfo = info; mMobileMappingsProxy = mobileMappingsProxy; - mFiveGStateListener = new FiveGStateListener(); - mFiveGState = new FiveGServiceState(); mNetworkNameSeparator = getTextIfExists( R.string.status_bar_network_name_separator).toString(); mNetworkNameDefault = getTextIfExists( @@ -467,12 +454,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile (showDataIconInStatusBar || mConfig.alwaysShowDataRatIcon) ? dataTypeIcon : 0; boolean showTriangle = mCurrentState.enabled && !mCurrentState.airplaneMode; - if ( mConfig.enableRatIconEnhancement ) { - typeIcon = getEnhancementDataRatIcon(); - }else if ( mConfig.enableDdsRatIconEnhancement ) { - typeIcon = getEnhancementDdsRatIcon(); - } - MobileIconGroup vowifiIconGroup = getVowifiIconGroup(); if (mConfig.showVowifiIcon && vowifiIconGroup != null) { typeIcon = vowifiIconGroup.dataType; @@ -663,14 +644,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile mCurrentState.iconGroup = mDefaultIcons; } - //Modem has centralized logic to display 5G icon based on carrier requirements - //For 5G icon display, only query NrIconType reported by modem - if ( mFiveGState.isNrIconTypeValid() ) { - mCurrentState.iconGroup = mFiveGState.getIconGroup(); - }else { - mCurrentState.iconGroup = getNetworkTypeIconGroup(); - } - mCurrentState.dataConnected = mCurrentState.isDataConnected(); mCurrentState.roaming = isRoaming(); @@ -699,16 +672,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile mCurrentState.networkNameData = mCurrentState.getOperatorAlphaShort(); } - - if ( mConfig.alwaysShowNetworkTypeIcon ) { - if(!mCurrentState.connected) { - mCurrentState.iconGroup = TelephonyIcons.UNKNOWN; - }else if (mFiveGState.isNrIconTypeValid()) { - mCurrentState.iconGroup = mFiveGState.getIconGroup(); - }else { - mCurrentState.iconGroup = getNetworkTypeIconGroup(); - } - } mCurrentState.mobileDataEnabled = mPhone.isDataEnabled(); mCurrentState.roamingDataEnabled = mPhone.isDataRoamingEnabled(); @@ -820,64 +783,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile mMobileStatusHistoryIndex = (mMobileStatusHistoryIndex + 1) % STATUS_HISTORY_SIZE; } - public void registerFiveGStateListener(FiveGServiceClient client) { - int phoneId = mSubscriptionInfo.getSimSlotIndex(); - client.registerListener(phoneId, mFiveGStateListener); - mClient = client; - } - - public void unregisterFiveGStateListener(FiveGServiceClient client) { - int phoneId = mSubscriptionInfo.getSimSlotIndex(); - client.unregisterListener(phoneId, mFiveGStateListener); - } - - private MobileIconGroup getNetworkTypeIconGroup() { - MobileIconGroup iconGroup = mDefaultIcons; - int overrideNetworkType = mCurrentState.telephonyDisplayInfo.getOverrideNetworkType(); - String iconKey = null; - if (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE - || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE - || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA ){ - int networkType = mCurrentState.telephonyDisplayInfo.getNetworkType(); - if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { - networkType = mCurrentState.getVoiceNetworkType(); - } - iconKey = toIconKey(networkType); - } else{ - iconKey = toDisplayIconKey(overrideNetworkType); - } - - return mNetworkToIconLookup.getOrDefault(iconKey, mDefaultIcons); - } - - private boolean showDataRatIcon() { - boolean result = false; - if ( mCurrentState.mobileDataEnabled ) { - if(mCurrentState.roamingDataEnabled || !mCurrentState.roaming) { - result = true; - } - } - return result; - } - - private int getEnhancementDataRatIcon() { - return showDataRatIcon() && mCurrentState.connected ? getRatIconGroup().dataType : 0; - } - - private int getEnhancementDdsRatIcon() { - return mCurrentState.dataSim && mCurrentState.connected ? getRatIconGroup().dataType : 0; - } - - private MobileIconGroup getRatIconGroup() { - MobileIconGroup iconGroup = mDefaultIcons; - if ( mFiveGState.isNrIconTypeValid() ) { - iconGroup = mFiveGState.getIconGroup(); - }else { - iconGroup = getNetworkTypeIconGroup(); - } - return iconGroup; - } - private boolean isVowifiAvailable() { return mCurrentState.voiceCapable && mCurrentState.imsRegistrationTech == REGISTRATION_TECH_IWLAN; @@ -899,9 +804,6 @@ public class MobileSignalController extends SignalController<MobileState, Mobile pw.println(" mSubscription=" + mSubscriptionInfo + ","); pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ","); pw.println(" isDataDisabled=" + isDataDisabled() + ","); - pw.println(" mConfig.enableRatIconEnhancement=" + mConfig.enableRatIconEnhancement + ","); - pw.println(" mConfig.enableDdsRatIconEnhancement=" - + mConfig.enableDdsRatIconEnhancement + ","); pw.println(" mConfig.alwaysShowNetworkTypeIcon=" + mConfig.alwaysShowNetworkTypeIcon + ","); pw.println(" mConfig.showVowifiIcon=" + mConfig.showVowifiIcon + ","); @@ -922,23 +824,9 @@ public class MobileSignalController extends SignalController<MobileState, Mobile + (mMobileStatusHistoryIndex + STATUS_HISTORY_SIZE - i) + "): " + mMobileStatusHistory[i & (STATUS_HISTORY_SIZE - 1)]); } - pw.println(" mFiveGState=" + mFiveGState + ","); - dumpTableData(pw); } - class FiveGStateListener implements IFiveGStateListener{ - - public void onStateChanged(FiveGServiceState state) { - if (DEBUG) { - Log.d(mTag, "onStateChanged: state=" + state); - } - mFiveGState = state; - updateTelephony(); - notifyListeners(); - } - } - private ImsMmTelManager.CapabilityCallback mCapabilityCallback = new ImsMmTelManager.CapabilityCallback() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 3e7bfa73da7e..1bd6850e422b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -86,7 +86,6 @@ import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DataSaverControllerImpl; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; -import com.android.systemui.statusbar.policy.FiveGServiceClient; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.util.CarrierConfigTracker; @@ -208,9 +207,6 @@ public class NetworkControllerImpl extends BroadcastReceiver private InternetDialogFactory mInternetDialogFactory; private Handler mMainHandler; - @VisibleForTesting - FiveGServiceClient mFiveGServiceClient; - private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @Override @@ -387,8 +383,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mWifiManager.registerScanResultsCallback(mReceiverHandler::post, scanResultsCallback); } - mFiveGServiceClient = FiveGServiceClient.getInstance(context); - NetworkCallback callback = new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO){ private Network mLastNetwork; @@ -500,7 +494,6 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.registerListener(); - mobileSignalController.registerFiveGStateListener(mFiveGServiceClient); } if (mSubscriptionListener == null) { mSubscriptionListener = new SubListener(mBgLooper); @@ -555,17 +548,11 @@ public class NetworkControllerImpl extends BroadcastReceiver for (int i = 0; i < mMobileSignalControllers.size(); i++) { MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i); mobileSignalController.unregisterListener(); - mobileSignalController.unregisterFiveGStateListener(mFiveGServiceClient); } mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener); mBroadcastDispatcher.unregisterReceiver(this); } - @VisibleForTesting - public FiveGServiceClient getFiveGServiceClient() { - return mFiveGServiceClient; - } - public int getConnectedWifiLevel() { return mWifiSignalController.getState().level; } @@ -1012,7 +999,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } if (mListening) { controller.registerListener(); - controller.registerFiveGStateListener(mFiveGServiceClient); } } } @@ -1023,7 +1009,6 @@ public class NetworkControllerImpl extends BroadcastReceiver mDefaultSignalController = null; } cachedControllers.get(key).unregisterListener(); - cachedControllers.get(key).unregisterFiveGStateListener(mFiveGServiceClient); } } mCallbackHandler.setSubs(subscriptions); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt index 90014c2518d1..78225dfe8d86 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt @@ -87,6 +87,7 @@ private class KeyguardNotificationVisibilityProviderImpl @Inject constructor( private val userTrackerCallback = object : UserTracker.Callback { override fun onUserChanged(newUser: Int, userContext: Context) { + readShowSilentNotificationSetting() if (isLockedOrLocking) { // maybe public mode changed notifyStateChanged("onUserSwitched") 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 0ccc81981e58..b4088d0db451 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -369,7 +369,10 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH, "com.android.systemui:CAMERA_GESTURE"); } - vibrateForCameraGesture(); + + if (source != StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) { + vibrateForCameraGesture(); + } if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) { Log.v(CentralSurfaces.TAG, "Camera launch"); 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 0f3f7434e603..8cd6ef276f2d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -1581,6 +1581,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_CAMERA_GESTURE); mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL); } @@ -2344,6 +2345,21 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { finishBarAnimations(); resetUserExpandedStates(); } + else if (Intent.ACTION_SCREEN_CAMERA_GESTURE.equals(action)) { + boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; + if (!userSetupComplete) { + if (DEBUG) Log.d(TAG, String.format( + "userSetupComplete = %s, ignoring camera launch gesture.", + userSetupComplete)); + return; + } + + // This gets executed before we will show Keyguard, so post it in order that the + // state is correct. + mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected( + StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE)); + } Trace.endSection(); } }; 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 f56b6cf03413..e8935765b8aa 100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -341,6 +341,9 @@ public class PhoneStatusBarPolicy mRecordingController.addCallback(this); mCommandQueue.addCallback(this); + + // Get initial user setup state + onUserSetupChanged(); } private String getManagedProfileAccessibilityString() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index fcae23b068bf..180758602998 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -328,7 +328,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue boolean showVibrateIcon = mSecureSettings.getIntForUser( Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, - 0, + 1, UserHandle.USER_CURRENT) == 0; // Filter out vibrate icon from the blocklist if the setting is on diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt index b845bada29dc..79d22bde3525 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt @@ -42,7 +42,7 @@ fun getStatusBarIconBlocklist( val vibrateIconSlot: String = res.getString(R.string.status_bar_volume) val showVibrateIcon = settings.getIntForUser( Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, - 0, + 1, UserHandle.USER_CURRENT) == 0 // Filter out vibrate icon from the blocklist if the setting is on diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileIconCustomizationMode.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileIconCustomizationMode.kt index 53955fc8a99c..c6b974600903 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileIconCustomizationMode.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/MobileIconCustomizationMode.kt @@ -8,14 +8,12 @@ package com.android.systemui.statusbar.pipeline.mobile.data.model import android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN import android.telephony.ims.stub.ImsRegistrationImplBase import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN -import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState data class MobileIconCustomizationMode( val alwaysUseRsrpLevelForLte: Boolean = false, val lteRsrpLevel: Int = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, val dataNetworkType: Int = NETWORK_TYPE_UNKNOWN, val voiceNetworkType: Int = NETWORK_TYPE_UNKNOWN, - val fiveGServiceState: FiveGServiceState = FiveGServiceState(), val isRatCustomization: Boolean = false, val alwaysShowNetworkTypeIcon: Boolean = false, val ddsRatIconEnhancementEnabled: Boolean = false, @@ -29,4 +27,4 @@ data class MobileIconCustomizationMode( val videoCapable: Boolean = false, val imsRegistered: Boolean = false, val imsRegistrationTech: Int = ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -)
\ No newline at end of file +) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index 13b3065b4027..3b434bae1b94 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -86,9 +86,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel -import com.android.systemui.statusbar.policy.FiveGServiceClient -import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState -import com.android.systemui.statusbar.policy.FiveGServiceClient.IFiveGStateListener import com.qti.extphone.NrIconType import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -129,7 +126,6 @@ class MobileConnectionRepositoryImpl( logger: MobileInputLogger, override val tableLogBuffer: TableLogBuffer, scope: CoroutineScope, - private val fiveGServiceClient: FiveGServiceClient, private val connectivityManager: ConnectivityManager ) : MobileConnectionRepository { init { @@ -173,8 +169,7 @@ class MobileConnectionRepositoryImpl( TelephonyCallback.DataActivityListener, TelephonyCallback.CarrierNetworkListener, TelephonyCallback.DisplayInfoListener, - TelephonyCallback.DataEnabledListener, - FiveGServiceClient.IFiveGStateListener { + TelephonyCallback.DataEnabledListener { override fun onServiceStateChanged(serviceState: ServiceState) { logger.logOnServiceStateChanged(serviceState, subId) trySend(CallbackEvent.OnServiceStateChanged(serviceState)) @@ -214,11 +209,6 @@ class MobileConnectionRepositoryImpl( logger.logOnDataEnabledChanged(enabled, subId) trySend(CallbackEvent.OnDataEnabledChanged(enabled)) } - - override fun onStateChanged(serviceState: FiveGServiceState) { - logger.logOnNrIconTypeChanged(serviceState.nrIconType, subId) - trySend(CallbackEvent.OnNrIconTypeChanged(serviceState.nrIconType)) - } } val imsStateCallback = @@ -238,7 +228,6 @@ class MobileConnectionRepositoryImpl( telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback) val slotIndex = getSlotIndex(subId) - fiveGServiceClient.registerListener(slotIndex, callback) try { imsMmTelManager.registerImsStateCallback(context.mainExecutor, imsStateCallback) } catch (exception: ImsException) { @@ -246,7 +235,6 @@ class MobileConnectionRepositoryImpl( } awaitClose { telephonyManager.unregisterTelephonyCallback(callback) - fiveGServiceClient.unregisterListener(slotIndex, callback) try { imsMmTelManager.unregisterImsStateCallback(imsStateCallback) } catch (exception: Exception) { @@ -614,7 +602,6 @@ class MobileConnectionRepositoryImpl( private val mobileMappingsProxy: MobileMappingsProxy, @Background private val bgDispatcher: CoroutineDispatcher, @Application private val scope: CoroutineScope, - private val fiveGServiceClient: FiveGServiceClient, private val connectivityManager: ConnectivityManager ) { fun build( @@ -636,7 +623,6 @@ class MobileConnectionRepositoryImpl( logger, mobileLogger, scope, - fiveGServiceClient, connectivityManager ) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt index faebb9d764c9..3343d4d6f6cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt @@ -45,7 +45,6 @@ import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIc import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel.DefaultIcon import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel.OverriddenIcon import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel -import com.android.systemui.statusbar.policy.FiveGServiceClient.FiveGServiceState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow @@ -278,7 +277,6 @@ class MobileIconInteractorImpl( MobileIconCustomizationMode( dataNetworkType = signalStrengthCustomization.dataNetworkType, voiceNetworkType = signalStrengthCustomization.voiceNetworkType, - fiveGServiceState = FiveGServiceState(nrIconType), isRatCustomization = networkTypeIconCustomization.isRatCustomization, alwaysShowNetworkTypeIcon = networkTypeIconCustomization.alwaysShowNetworkTypeIcon, @@ -336,8 +334,7 @@ class MobileIconInteractorImpl( is ResolvedNetworkType.CarrierMergedNetworkType -> resolvedNetworkType.iconGroupOverride else -> { - getMobileIconGroup(resolvedNetworkType, mobileIconCustomization, mapping) - ?: defaultGroup + mapping[resolvedNetworkType.lookupKey] ?: defaultGroup } } } @@ -425,39 +422,4 @@ class MobileIconInteractorImpl( || mobileIconCustmization.voiceNetworkType == TelephonyManager.NETWORK_TYPE_LTE || mobileIconCustmization.voiceNetworkType == TelephonyManager.NETWORK_TYPE_LTE_CA) } - - private fun getMobileIconGroup(resolvedNetworkType: ResolvedNetworkType, - customizationInfo: MobileIconCustomizationMode, - mapping: Map<String, MobileIconGroup>): MobileIconGroup ?{ - return if (customizationInfo.fiveGServiceState.isNrIconTypeValid) { - customizationInfo.fiveGServiceState.iconGroup - } else { - when (resolvedNetworkType) { - is DefaultNetworkType -> - mapping[resolvedNetworkType.lookupKey] - is OverrideNetworkType -> - mapping[getLookupKey(resolvedNetworkType, customizationInfo)] - else -> - mapping[MobileMappings.toIconKey(customizationInfo.voiceNetworkType)] - } - } - } - - private fun getLookupKey(resolvedNetworkType: ResolvedNetworkType, - customizationInfo: MobileIconCustomizationMode): String { - return if (isNsa(resolvedNetworkType.networkType)) { - if (customizationInfo.dataNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { - MobileMappings.toIconKey(customizationInfo.voiceNetworkType) - }else { - MobileMappings.toIconKey(customizationInfo.dataNetworkType) - } - }else { - resolvedNetworkType.lookupKey - } - } - - private fun isNsa(networkType: Int): Boolean { - return networkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE - || networkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java deleted file mode 100644 index 11e0949da463..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FiveGServiceClient.java +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of The Linux Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.android.systemui.statusbar.policy; - -import android.content.ComponentName; -import android.content.Context; -import android.content.ServiceConnection; -import android.net.Uri; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.DeadObjectException; -import android.os.RemoteException; -import android.util.Log; -import android.util.SparseArray; - -import com.google.android.collect.Lists; -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.Exception; -import java.util.ArrayList; -import java.util.concurrent.CopyOnWriteArrayList; -import java.lang.ref.WeakReference; -import javax.inject.Inject; - -import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.settingslib.mobile.TelephonyIcons; -import com.android.settingslib.SignalIcon.MobileIconGroup; -import com.android.systemui.R; -import com.android.systemui.dagger.SysUISingleton; - -import com.qti.extphone.Client; -import com.qti.extphone.ExtTelephonyManager; -import com.qti.extphone.IExtPhoneCallback; -import com.qti.extphone.ExtPhoneCallbackListener; -import com.qti.extphone.NrIconType; -import com.qti.extphone.Status; -import com.qti.extphone.ServiceCallback; -import com.qti.extphone.Token; - -@SysUISingleton -public class FiveGServiceClient { - private static final String TAG = "FiveGServiceClient"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG)||true; - private static final int MESSAGE_REBIND = 1024; - private static final int MESSAGE_REINIT = MESSAGE_REBIND+1; - private static final int MESSAGE_NOTIFIY_MONITOR_CALLBACK = MESSAGE_REBIND+2; - private static final int MAX_RETRY = 4; - private static final int DELAY_MILLISECOND = 3000; - private static final int DELAY_INCREMENT = 2000; - - private static FiveGServiceClient sInstance; - private final ArrayList<WeakReference<KeyguardUpdateMonitorCallback>> - mKeyguardUpdateMonitorCallbacks = Lists.newArrayList(); - @VisibleForTesting - final SparseArray<CopyOnWriteArrayList<IFiveGStateListener>> mStatesListeners = - new SparseArray<>(); - private final SparseArray<FiveGServiceState> mCurrentServiceStates = new SparseArray<>(); - private final SparseArray<FiveGServiceState> mLastServiceStates = new SparseArray<>(); - - private Context mContext; - private boolean mServiceConnected; - private String mPackageName; - private Client mClient; - private int mInitRetryTimes = 0; - private ExtTelephonyManager mExtTelephonyManager; - private boolean mIsConnectInProgress = false; - - public static class FiveGServiceState{ - private static final String COL_NR_ICON_TYPE = "NrIconType"; - private int mNrIconType; - private MobileIconGroup mIconGroup; - - public FiveGServiceState(){ - mNrIconType = NrIconType.INVALID; - mIconGroup = TelephonyIcons.UNKNOWN; - } - - @VisibleForTesting - public FiveGServiceState(int nrIconType){ - mNrIconType = nrIconType; - mIconGroup = getNrIconGroup(nrIconType, 0); - } - - public boolean isNrIconTypeValid() { - return mNrIconType != NrIconType.INVALID && mNrIconType != NrIconType.TYPE_NONE; - } - - @VisibleForTesting - public MobileIconGroup getIconGroup() { - return mIconGroup; - } - - @VisibleForTesting - public int getNrIconType() { - return mNrIconType; - } - - public void copyFrom(FiveGServiceState state) { - this.mIconGroup = state.mIconGroup; - this.mNrIconType = state.mNrIconType; - } - - public boolean equals(FiveGServiceState state) { - return this.mIconGroup == state.mIconGroup - && this.mNrIconType == state.mNrIconType; - } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("mNrIconType=").append(mNrIconType).append(", "). - append("mIconGroup=").append(mIconGroup); - - return builder.toString(); - } - } - - @Inject - public FiveGServiceClient(Context context) { - mContext = context; - mPackageName = mContext.getPackageName(); - if (mExtTelephonyManager == null) { - mExtTelephonyManager = ExtTelephonyManager.getInstance(mContext); - } - } - - public static FiveGServiceClient getInstance(Context context) { - if ( sInstance == null ) { - sInstance = new FiveGServiceClient(context); - } - - return sInstance; - } - - public void registerCallback(KeyguardUpdateMonitorCallback callback) { - mKeyguardUpdateMonitorCallbacks.add( - new WeakReference<KeyguardUpdateMonitorCallback>(callback)); - } - - public void registerListener(int phoneId, IFiveGStateListener listener) { - Log.d(TAG, "registerListener phoneId=" + phoneId + " listener: " + listener); - resetState(phoneId); - CopyOnWriteArrayList<IFiveGStateListener> statesListenersForPhone = - mStatesListeners.get(phoneId); - if (statesListenersForPhone == null) { - statesListenersForPhone = new CopyOnWriteArrayList<>(); - mStatesListeners.put(phoneId, statesListenersForPhone); - } - statesListenersForPhone.add(listener); - - if ( !isServiceConnected() ) { - connectService(); - }else{ - initFiveGServiceState(phoneId); - } - } - - private void resetState(int phoneId) { - Log.d(TAG, "resetState phoneId=" + phoneId); - FiveGServiceState currentState = getCurrentServiceState(phoneId); - currentState.mNrIconType = NrIconType.INVALID; - currentState.mIconGroup = TelephonyIcons.UNKNOWN; - - FiveGServiceState lastState = getLastServiceState(phoneId); - lastState.mNrIconType = NrIconType.INVALID; - lastState.mIconGroup = TelephonyIcons.UNKNOWN; - } - - public void unregisterListener(int phoneId, IFiveGStateListener fiveGStateListener) { - Log.d(TAG, "unregisterListener phoneId=" + phoneId + " listener: " + fiveGStateListener); - CopyOnWriteArrayList<IFiveGStateListener> statesListenersForPhone = - mStatesListeners.get(phoneId); - if (statesListenersForPhone != null) { - statesListenersForPhone.remove(fiveGStateListener); - if (statesListenersForPhone.size() == 0) { - mStatesListeners.remove(phoneId); - mCurrentServiceStates.remove(phoneId); - mLastServiceStates.remove(phoneId); - } - } - } - - public boolean isServiceConnected() { - return mServiceConnected; - } - - private void connectService() { - if (!isServiceConnected() && !mIsConnectInProgress) { - mIsConnectInProgress = true; - Log.d(TAG, "Connect to ExtTelephony bound service..."); - mExtTelephonyManager.connectService(mServiceCallback); - } - } - - private ServiceCallback mServiceCallback = new ServiceCallback() { - @Override - public void onConnected() { - Log.d(TAG, "ExtTelephony Service connected"); - int[] events = new int[] { - ExtPhoneCallbackListener.EVENT_ON_NR_ICON_TYPE}; - mServiceConnected = true; - mIsConnectInProgress = false; - mClient = mExtTelephonyManager.registerCallbackWithEvents( - mPackageName, mExtPhoneCallbackListener, events); - initFiveGServiceState(); - Log.d(TAG, "Client = " + mClient); - } - @Override - public void onDisconnected() { - Log.d(TAG, "ExtTelephony Service disconnected..."); - if (mServiceConnected) { - mExtTelephonyManager.unregisterCallback(mExtPhoneCallbackListener); - } - mServiceConnected = false; - mClient = null; - mIsConnectInProgress = false; - mHandler.sendEmptyMessageDelayed(MESSAGE_REBIND, - DELAY_MILLISECOND + DELAY_INCREMENT); - } - }; - - @VisibleForTesting - public FiveGServiceState getCurrentServiceState(int phoneId) { - return getServiceState(phoneId, mCurrentServiceStates); - } - - private FiveGServiceState getLastServiceState(int phoneId) { - return getServiceState(phoneId, mLastServiceStates); - } - - private static FiveGServiceState getServiceState(int key, - SparseArray<FiveGServiceState> array) { - FiveGServiceState state = array.get(key); - if ( state == null ) { - state = new FiveGServiceState(); - array.put(key, state); - } - return state; - } - - private void notifyListenersIfNecessary(int phoneId) { - FiveGServiceState currentState = getCurrentServiceState(phoneId); - FiveGServiceState lastState = getLastServiceState(phoneId); - if ( !currentState.equals(lastState) ) { - - if ( DEBUG ) { - Log.d(TAG, "phoneId(" + phoneId + ") Change in state from " + lastState + " \n"+ - "\tto " + currentState); - - } - - lastState.copyFrom(currentState); - CopyOnWriteArrayList<IFiveGStateListener> statesListenersForPhone = - mStatesListeners.get(phoneId); - if (statesListenersForPhone != null) { - for (IFiveGStateListener listener: statesListenersForPhone) { - if (listener != null) { - listener.onStateChanged(currentState); - } - } - } - mHandler.sendEmptyMessage(MESSAGE_NOTIFIY_MONITOR_CALLBACK); - } - } - - private void initFiveGServiceState() { - Log.d(TAG, "initFiveGServiceState size=" + mStatesListeners.size()); - for( int i=0; i < mStatesListeners.size(); ++i ) { - int phoneId = mStatesListeners.keyAt(i); - initFiveGServiceState(phoneId); - } - } - - private void initFiveGServiceState(int phoneId) { - Log.d(TAG, "mServiceConnected=" + mServiceConnected + " mClient=" + mClient); - if ( mServiceConnected && mClient != null) { - Log.d(TAG, "query 5G service state for phoneId " + phoneId); - try { - Token token = mExtTelephonyManager.queryNrIconType(phoneId, mClient); - Log.d(TAG, "queryNrIconType result:" + token); - } catch (Exception e) { - Log.d(TAG, "initFiveGServiceState: Exception = " + e); - if ( mInitRetryTimes < MAX_RETRY && !mHandler.hasMessages(MESSAGE_REINIT) ) { - mHandler.sendEmptyMessageDelayed(MESSAGE_REINIT, - DELAY_MILLISECOND + mInitRetryTimes*DELAY_INCREMENT); - mInitRetryTimes +=1; - } - } - } - } - - @VisibleForTesting - void update5GIcon(FiveGServiceState state,int phoneId) { - state.mIconGroup = getNrIconGroup(state.mNrIconType, phoneId); - } - - private static MobileIconGroup getNrIconGroup(int nrIconType , int phoneId) { - MobileIconGroup iconGroup = TelephonyIcons.UNKNOWN; - switch (nrIconType){ - case NrIconType.TYPE_5G_BASIC: - iconGroup = TelephonyIcons.FIVE_G_BASIC; - break; - case NrIconType.TYPE_5G_UWB: - iconGroup = TelephonyIcons.FIVE_G_UWB; - break; - } - return iconGroup; - } - - private void notifyMonitorCallback() { - for (int i = 0; i < mKeyguardUpdateMonitorCallbacks.size(); i++) { - KeyguardUpdateMonitorCallback cb = mKeyguardUpdateMonitorCallbacks.get(i).get(); - if (cb != null) { - cb.onRefreshCarrierInfo(); - } - } - } - - private Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - int what = msg.what; - switch ( msg.what ) { - case MESSAGE_REBIND: - connectService(); - break; - - case MESSAGE_REINIT: - initFiveGServiceState(); - break; - - case MESSAGE_NOTIFIY_MONITOR_CALLBACK: - notifyMonitorCallback(); - break; - } - - } - }; - - - @VisibleForTesting - protected ExtPhoneCallbackListener mExtPhoneCallbackListener = new ExtPhoneCallbackListener() { - @Override - public void onNrIconType(int slotId, Token token, Status status, NrIconType - nrIconType) throws RemoteException { - Log.d(TAG, - "onNrIconType: slotId = " + slotId + " token = " + token + " " + "status" - + status + " NrIconType = " + nrIconType); - if (status.get() == Status.SUCCESS) { - FiveGServiceState state = getCurrentServiceState(slotId); - state.mNrIconType = nrIconType.get(); - update5GIcon(state, slotId); - notifyListenersIfNecessary(slotId); - } - } - }; - - public interface IFiveGStateListener { - public void onStateChanged(FiveGServiceState state); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java new file mode 100644 index 000000000000..5fed8858c34d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiController.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Paranoid Android + * + * 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.tristate; + +import com.android.systemui.plugins.Plugin; +import com.android.systemui.plugins.VolumeDialog.Callback; +import com.android.systemui.plugins.annotations.DependsOn; +import com.android.systemui.plugins.annotations.ProvidesInterface; + +@DependsOn(target = Callback.class) +@ProvidesInterface(action = "com.android.systemui.action.PLUGIN_TRI_STATE_UI", version = 1) +public interface TriStateUiController extends Plugin { + + public interface UserActivityListener { + void onTriStateUserActivity(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java new file mode 100644 index 000000000000..941c91b9d1a0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tristate/TriStateUiControllerImpl.java @@ -0,0 +1,487 @@ +/* + * Copyright 2019 Paranoid Android + * + * 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.tristate; + +import static android.view.Surface.ROTATION_90; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; + +import android.app.Dialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.ColorDrawable; +import android.hardware.display.DisplayManagerGlobal; +import android.media.AudioManager; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings; +import android.util.Log; +import android.view.Display; +import android.view.OrientationEventListener; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager.LayoutParams; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.internal.policy.SystemBarUtils; +import com.android.systemui.R; +import com.android.systemui.tristate.TriStateUiController; +import com.android.systemui.tristate.TriStateUiController.UserActivityListener; +import com.android.systemui.plugins.VolumeDialogController; +import com.android.systemui.plugins.VolumeDialogController.Callbacks; +import com.android.systemui.plugins.VolumeDialogController.State; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; + +public class TriStateUiControllerImpl implements ConfigurationListener, TriStateUiController { + + private static String TAG = "TriStateUiControllerImpl"; + + private static final int MSG_DIALOG_SHOW = 1; + private static final int MSG_DIALOG_DISMISS = 2; + private static final int MSG_RESET_SCHEDULE = 3; + private static final int MSG_STATE_CHANGE = 4; + + private static final int MODE_NORMAL = AudioManager.RINGER_MODE_NORMAL; + private static final int MODE_SILENT = AudioManager.RINGER_MODE_SILENT; + private static final int MODE_VIBRATE = AudioManager.RINGER_MODE_VIBRATE; + + private static final int TRI_STATE_UI_POSITION_LEFT = 0; + private static final int TRI_STATE_UI_POSITION_RIGHT = 1; + + private static final int DIALOG_TIMEOUT = 2000; + + private Context mContext; + private final VolumeDialogController mVolumeDialogController; + private final ConfigurationController mConfigurationController; + private final Callbacks mVolumeDialogCallback = new Callbacks() { + @Override + public void onShowRequested(int reason, boolean keyguardLocked, int lockTaskModeState) { } + + @Override + public void onDismissRequested(int reason) { } + + @Override + public void onScreenOff() { } + + @Override + public void onStateChanged(State state) { } + + @Override + public void onLayoutDirectionChanged(int layoutDirection) { } + + @Override + public void onShowVibrateHint() { } + + @Override + public void onShowSilentHint() { } + + @Override + public void onShowSafetyWarning(int flags) { } + + @Override + public void onShowCsdWarning(int csdWarning, int durationMs) { } + + @Override + public void onAccessibilityModeChanged(Boolean showA11yStream) { } + + @Override + public void onCaptionComponentStateChanged( + Boolean isComponentEnabled, Boolean fromTooltip) {} + + @Override + public void onConfigurationChanged() { + updateTheme(); + updateTriStateLayout(); + } + }; + + private int mDensity; + private Dialog mDialog; + private int mDialogPosition; + private ViewGroup mDialogView; + private final H mHandler; + private UserActivityListener mListener; + OrientationEventListener mOrientationListener; + private int mOrientationType = 0; + private boolean mShowing = false; + private int mBackgroundColor = 0; + private int mThemeMode = 0; + private int mIconColor = 0; + private int mTextColor = 0; + private ImageView mTriStateIcon; + private TextView mTriStateText; + private int mTriStateMode = -1; + private Window mWindow; + private LayoutParams mWindowLayoutParams; + private int mWindowType; + + private final BroadcastReceiver mRingerStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateRingerModeChanged(); + } + }; + + private final class H extends Handler { + private TriStateUiControllerImpl mUiController; + + public H(TriStateUiControllerImpl uiController) { + super(Looper.getMainLooper()); + mUiController = uiController; + } + + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DIALOG_SHOW: + mUiController.handleShow(); + return; + case MSG_DIALOG_DISMISS: + mUiController.handleDismiss(); + return; + case MSG_RESET_SCHEDULE: + mUiController.handleResetTimeout(); + return; + case MSG_STATE_CHANGE: + mUiController.handleStateChanged(); + return; + default: + return; + } + } + } + + public TriStateUiControllerImpl( + Context context, + VolumeDialogController volumeDialogController, + ConfigurationController configurationController) { + mContext = context; + mVolumeDialogController = volumeDialogController; + mConfigurationController = configurationController; + mHandler = new H(this); + mOrientationListener = new OrientationEventListener(mContext, 3) { + @Override + public void onOrientationChanged(int orientation) { + checkOrientationType(); + } + }; + IntentFilter ringerChanged = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); + mContext.registerReceiver(mRingerStateReceiver, ringerChanged); + } + + private void checkOrientationType() { + Display display = DisplayManagerGlobal.getInstance().getRealDisplay(0); + if (display != null) { + int rotation = display.getRotation(); + if (rotation != mOrientationType) { + mOrientationType = rotation; + updateTriStateLayout(); + } + } + } + + public void init(int windowType, UserActivityListener listener) { + mWindowType = windowType; + mDensity = mContext.getResources().getConfiguration().densityDpi; + mListener = listener; + mConfigurationController.addCallback(this); + mVolumeDialogController.addCallback(mVolumeDialogCallback, mHandler); + initDialog(); + } + + public void destroy() { + mConfigurationController.addCallback(this); + mVolumeDialogController.removeCallback(mVolumeDialogCallback); + mContext.unregisterReceiver(mRingerStateReceiver); + } + + private void initDialog() { + if (mDialog != null) { + mDialog.dismiss(); + mDialog = null; + } + mDialog = new Dialog(mContext); + mShowing = false; + mWindow = mDialog.getWindow(); + mWindow.requestFeature(Window.FEATURE_NO_TITLE); + mWindow.setBackgroundDrawable(new ColorDrawable(0)); + mWindow.clearFlags(LayoutParams.FLAG_DIM_BEHIND); + mWindow.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE + | LayoutParams.FLAG_LAYOUT_IN_SCREEN + | LayoutParams.FLAG_NOT_TOUCH_MODAL + | LayoutParams.FLAG_SHOW_WHEN_LOCKED + | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | LayoutParams.FLAG_HARDWARE_ACCELERATED); + mDialog.setCanceledOnTouchOutside(false); + mWindowLayoutParams = mWindow.getAttributes(); + mWindowLayoutParams.type = mWindowType; + mWindowLayoutParams.format = -3; + mWindowLayoutParams.setTitle(TriStateUiControllerImpl.class.getSimpleName()); + mWindowLayoutParams.gravity = 53; + mWindowLayoutParams.y = mDialogPosition; + mWindow.setAttributes(mWindowLayoutParams); + mWindow.setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING); + mDialog.setContentView(R.layout.tri_state_dialog); + mDialogView = (ViewGroup) mDialog.findViewById(R.id.tri_state_layout); + mTriStateIcon = (ImageView) mDialog.findViewById(R.id.tri_state_icon); + mTriStateText = (TextView) mDialog.findViewById(R.id.tri_state_text); + updateTheme(); + } + + public void show() { + mHandler.obtainMessage(MSG_DIALOG_SHOW, 0, 0).sendToTarget(); + } + + private void registerOrientationListener(boolean enable) { + if (mOrientationListener.canDetectOrientation() && enable) { + Log.v(TAG, "Can detect orientation"); + mOrientationListener.enable(); + return; + } + Log.v(TAG, "Cannot detect orientation"); + mOrientationListener.disable(); + } + + private void updateTriStateLayout() { + if (mContext != null) { + int iconId = 0; + int textId = 0; + int bg = 0; + Resources res = mContext.getResources(); + if (res != null) { + int positionY; + int positionY2 = mWindowLayoutParams.y; + int positionX = mWindowLayoutParams.x; + int gravity = mWindowLayoutParams.gravity; + switch (mTriStateMode) { + case MODE_SILENT: + iconId = R.drawable.ic_volume_ringer_mute; + textId = R.string.volume_ringer_status_silent; + break; + case MODE_VIBRATE: + iconId = R.drawable.ic_volume_ringer_vibrate; + textId = R.string.volume_ringer_status_vibrate; + break; + case MODE_NORMAL: + iconId = R.drawable.ic_volume_ringer; + textId = R.string.volume_ringer_status_normal; + break; + } + int triStatePos = res.getInteger( + com.android.internal.R.integer.config_alertSliderLocation); + boolean isTsKeyRight = + (triStatePos == TRI_STATE_UI_POSITION_LEFT) ? false : true; + switch (mOrientationType) { + case ROTATION_90: + gravity = (isTsKeyRight) ? 51 : 83; + positionY2 = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_deep_land); + if (isTsKeyRight) { + positionY2 += SystemBarUtils.getStatusBarHeight(mContext); + } + if (mTriStateMode == MODE_SILENT) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_l); + } else if (mTriStateMode == MODE_VIBRATE) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_middle_dialog_position_l); + } else if (mTriStateMode == MODE_NORMAL) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_down_dialog_position_l); + } + bg = R.drawable.dialog_tri_state_middle_bg; + break; + case ROTATION_180: + gravity = (isTsKeyRight) ? 83 : 85; + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_deep); + positionY2 = SystemBarUtils.getStatusBarHeight(mContext); + bg = R.drawable.dialog_tri_state_middle_bg; + if (mTriStateMode != MODE_SILENT) { + if (mTriStateMode != MODE_VIBRATE) { + if (mTriStateMode == MODE_NORMAL) { + positionY2 += res.getDimensionPixelSize( + R.dimen.tri_state_down_dialog_position); + break; + } + } + positionY2 += res.getDimensionPixelSize( + R.dimen.tri_state_middle_dialog_position); + break; + } + positionY2 += res.getDimensionPixelSize(R.dimen.tri_state_up_dialog_position); + break; + case ROTATION_270: + gravity = (isTsKeyRight) ? 85 : 53; + positionY2 = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_deep_land); + if (!isTsKeyRight) { + positionY2 += SystemBarUtils.getStatusBarHeight(mContext); + } + if (mTriStateMode == MODE_SILENT) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_l); + } else if (mTriStateMode == MODE_VIBRATE) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_middle_dialog_position_l); + } else if (mTriStateMode == MODE_NORMAL) { + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_down_dialog_position_l); + } + bg = R.drawable.dialog_tri_state_middle_bg; + break; + default: + gravity = (isTsKeyRight) ? 53 : 51; + positionX = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position_deep); + if (mTriStateMode != MODE_SILENT) { + if (mTriStateMode != MODE_VIBRATE) { + if (mTriStateMode == MODE_NORMAL) { + positionY2 = res.getDimensionPixelSize( + R.dimen.tri_state_down_dialog_position) + + SystemBarUtils.getStatusBarHeight(mContext); + bg = R.drawable.dialog_tri_state_down_bg; + break; + } + } + positionY2 = res.getDimensionPixelSize( + R.dimen.tri_state_middle_dialog_position) + + SystemBarUtils.getStatusBarHeight(mContext); + bg = R.drawable.dialog_tri_state_middle_bg; + break; + } + positionY2 = res.getDimensionPixelSize( + R.dimen.tri_state_up_dialog_position) + + SystemBarUtils.getStatusBarHeight(mContext); + bg = R.drawable.dialog_tri_state_up_bg; + break; + } + if (mTriStateMode != -1) { + if (mTriStateIcon != null && iconId != 0) { + mTriStateIcon.setImageResource(iconId); + } + if (mTriStateText != null && textId != 0) { + String inputText = res.getString(textId); + if (inputText != null && mTriStateText.length() == inputText.length()) { + StringBuilder sb = new StringBuilder(); + sb.append(inputText); + sb.append(" "); + inputText = sb.toString(); + } + mTriStateText.setText(inputText); + } + if (mDialogView != null && bg != 0) { + mDialogView.setBackgroundDrawable(res.getDrawable(bg)); + } + mDialogPosition = positionY2; + } + positionY = res.getDimensionPixelSize(R.dimen.tri_state_dialog_padding); + mWindowLayoutParams.gravity = gravity; + mWindowLayoutParams.y = positionY2 - positionY; + mWindowLayoutParams.x = positionX - positionY; + mWindow.setAttributes(mWindowLayoutParams); + handleResetTimeout(); + } + } + } + + private void updateRingerModeChanged() { + mHandler.obtainMessage(MSG_STATE_CHANGE, 0, 0).sendToTarget(); + if (mTriStateMode != -1) { + show(); + } + } + + private void handleShow() { + mHandler.removeMessages(MSG_DIALOG_SHOW); + mHandler.removeMessages(MSG_DIALOG_DISMISS); + handleResetTimeout(); + if (!mShowing) { + updateTheme(); + registerOrientationListener(true); + checkOrientationType(); + mShowing = true; + mDialog.show(); + if (mListener != null) { + mListener.onTriStateUserActivity(); + } + } + } + + private void handleDismiss() { + mHandler.removeMessages(MSG_DIALOG_SHOW); + mHandler.removeMessages(MSG_DIALOG_DISMISS); + if (mShowing) { + registerOrientationListener(false); + mShowing = false; + mDialog.dismiss(); + } + } + + private void handleStateChanged() { + AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + int ringerMode = am.getRingerModeInternal(); + if (ringerMode != mTriStateMode) { + mTriStateMode = ringerMode; + updateTriStateLayout(); + if (mListener != null) { + mListener.onTriStateUserActivity(); + } + } + } + + public void handleResetTimeout() { + mHandler.removeMessages(MSG_DIALOG_DISMISS); + mHandler.sendMessageDelayed(mHandler.obtainMessage( + MSG_DIALOG_DISMISS, MSG_RESET_SCHEDULE, 0), (long) DIALOG_TIMEOUT); + if (mListener != null) { + mListener.onTriStateUserActivity(); + } + } + + @Override + public void onDensityOrFontScaleChanged() { + handleDismiss(); + initDialog(); + updateTriStateLayout(); + } + + private void updateTheme() { + // Todo: Add some logic to update the theme only when a new theme is applied + mIconColor = getAttrColor(android.R.attr.colorAccent); + mTextColor = getAttrColor(android.R.attr.textColorPrimary); + mBackgroundColor = getAttrColor(android.R.attr.colorPrimary); + mDialogView.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); + mTriStateIcon.setColorFilter(mIconColor); + mTriStateText.setTextColor(mTextColor); + } + + public int getAttrColor(int attr) { + TypedArray ta = mContext.obtainStyledAttributes(new int[]{attr}); + int colorAccent = ta.getColor(0, 0); + ta.recycle(); + return colorAccent; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index 246488600eef..fc05d9b5ef02 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -19,7 +19,6 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.view.MenuItem; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; @@ -87,18 +86,6 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference mDemoModeTracker.startTracking(); updateDemoModeEnabled(); updateDemoModeOn(); - - setHasOptionsMenu(true); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getFragmentManager().popBackStack(); - break; - } - return super.onOptionsItemSelected(item); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarTuner.java new file mode 100644 index 000000000000..c1447e6c7ab4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarTuner.java @@ -0,0 +1,44 @@ +/* + * 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.tuner; + +import android.os.Bundle; + +import androidx.preference.PreferenceFragment; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.R; + +public class StatusBarTuner extends PreferenceFragment { + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.status_bar_prefs); + } + + @Override + public void onResume() { + super.onResume(); + MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, true); + } + + @Override + public void onPause() { + super.onPause(); + MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java index 32ecb6786a51..fc91ff129c06 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java @@ -15,20 +15,17 @@ */ package com.android.systemui.tuner; -import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.util.Log; -import android.view.MenuItem; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Toolbar; import androidx.preference.Preference; import androidx.preference.PreferenceFragment; import androidx.preference.PreferenceScreen; +import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity; + import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.demomode.DemoModeController; @@ -37,7 +34,7 @@ import com.android.systemui.util.settings.GlobalSettings; import javax.inject.Inject; -public class TunerActivity extends Activity implements +public class TunerActivity extends CollapsingToolbarBaseActivity implements PreferenceFragment.OnPreferenceStartFragmentCallback, PreferenceFragment.OnPreferenceStartScreenCallback { @@ -61,23 +58,19 @@ public class TunerActivity extends Activity implements protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setTheme(R.style.Theme_AppCompat_DayNight); - - getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.tuner_activity); - Toolbar toolbar = findViewById(R.id.action_bar); - if (toolbar != null) { - setActionBar(toolbar); - } if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) { final String action = getIntent().getAction(); - boolean showDemoMode = action != null && action.equals( - "com.android.settings.action.DEMO_MODE"); - final PreferenceFragment fragment = showDemoMode - ? new DemoModeFragment(mDemoModeController, mGlobalSettings) - : new TunerFragment(mTunerService); + final Fragment fragment; + if ("com.android.settings.action.DEMO_MODE".equals(action)) { + fragment = new DemoModeFragment(mDemoModeController, mGlobalSettings); + } else if ("com.android.settings.action.STATUS_BAR_TUNER".equals(action)) { + fragment = new StatusBarTuner(); + } else { + fragment = new TunerFragment(mTunerService); + } + getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, TAG_TUNER).commit(); } @@ -90,15 +83,6 @@ public class TunerActivity extends Activity implements } @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - return super.onMenuItemSelected(featureId, item); - } - - @Override public void onBackPressed() { if (!getFragmentManager().popBackStackImmediate()) { super.onBackPressed(); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java index 989462a9fd34..c1bb0ea68ec7 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java @@ -16,17 +16,9 @@ package com.android.systemui.tuner; import android.annotation.SuppressLint; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; import android.hardware.display.AmbientDisplayConfiguration; import android.os.Build; import android.os.Bundle; -import android.provider.Settings; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import androidx.preference.Preference; import androidx.preference.PreferenceFragment; @@ -53,8 +45,6 @@ public class TunerFragment extends PreferenceFragment { "picture_in_picture", }; - private static final int MENU_REMOVE = Menu.FIRST + 1; - private final TunerService mTunerService; // We are the only ones who ever call this constructor, so don't worry about the warning @@ -67,14 +57,6 @@ public class TunerFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - setHasOptionsMenu(true); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); } @Override @@ -92,13 +74,6 @@ public class TunerFragment extends PreferenceFragment { if (preference != null) getPreferenceScreen().removePreference(preference); } } - - if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING, - 0) == 0) { - if (getFragmentManager().findFragmentByTag(WARNING_TAG) == null) { - new TunerWarningFragment().show(getFragmentManager(), WARNING_TAG); - } - } } private boolean alwaysOnAvailable() { @@ -119,42 +94,4 @@ public class TunerFragment extends PreferenceFragment { MetricsLogger.visibility(getContext(), MetricsEvent.TUNER, false); } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - getActivity().finish(); - return true; - case MENU_REMOVE: - mTunerService.showResetRequest(() -> { - if (getActivity() != null) { - getActivity().finish(); - } - }); - return true; - } - return super.onOptionsItemSelected(item); - } - - public static class TunerWarningFragment extends DialogFragment { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return new AlertDialog.Builder(getContext()) - .setTitle(R.string.tuner_warning_title) - .setMessage(R.string.tuner_warning) - .setPositiveButton(R.string.got_it, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Settings.Secure.putInt(getContext().getContentResolver(), - SETTING_SEEN_TUNER_WARNING, 1); - } - }).show(); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 095718bddf97..fc88f5be69d7 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -394,9 +394,8 @@ public class StorageNotification implements CoreStartable { final VolumeRecord rec = mStorageManager.findRecordByUuid(vol.getFsUuid()); final DiskInfo disk = vol.getDisk(); - // Don't annoy when user dismissed in past. (But make sure the disk is adoptable; we - // used to allow snoozing non-adoptable disks too.) - if (rec == null || (rec.isSnoozed() && disk.isAdoptable())) { + // Don't annoy when user dismissed in past. + if (rec == null || (rec.isSnoozed() && (disk.isAdoptable() || disk.isSd()))) { return null; } if (disk.isAdoptable() && !rec.isInited() && rec.getType() != VolumeInfo.TYPE_PUBLIC @@ -439,8 +438,12 @@ public class StorageNotification implements CoreStartable { buildUnmountPendingIntent(vol))) .setContentIntent(browseIntent) .setCategory(Notification.CATEGORY_SYSTEM); - // Non-adoptable disks can't be snoozed. - if (disk.isAdoptable()) { + // USB disks notification can be persistent + if (disk.isUsb()) { + builder.setOngoing(true); + } + + if (disk.isAdoptable() || disk.isSd()) { builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid())); } diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierNameCustomization.java b/packages/SystemUI/src/com/android/systemui/util/CarrierNameCustomization.java deleted file mode 100644 index 3d80735f09eb..000000000000 --- a/packages/SystemUI/src/com/android/systemui/util/CarrierNameCustomization.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. - * SPDX-License-Identifier: BSD-3-Clause-Clear - */ -package com.android.systemui.util; - -import android.content.Context; -import android.telephony.SubscriptionInfo; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Log; - -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.R; - -import java.util.HashMap; -import javax.inject.Inject; - -@SysUISingleton -public class CarrierNameCustomization { - private final String TAG = "CarrierNameCustomization"; - private final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - /** - * The map for carriers: - * The key is MCCMNC. - * The value of the key is unique carrier name. - * Carrier can have several MCCMNC, but it only has one unique carrier name. - */ - private HashMap<String, String> mCarrierMap; - private boolean mRoamingCustomizationCarrierNameEnabled; - private String mConnector; - private TelephonyManager mTelephonyManager; - - @Inject - public CarrierNameCustomization(Context context) { - mCarrierMap = new HashMap<String, String>(); - - mRoamingCustomizationCarrierNameEnabled = context.getResources().getBoolean( - R.bool.config_show_roaming_customization_carrier_name); - mConnector = context.getResources().getString(R.string.connector); - - mTelephonyManager = context.getSystemService(TelephonyManager.class); - - if (mRoamingCustomizationCarrierNameEnabled) { - loadCarrierMap(context); - } - } - - /** - * Returns true if the roaming customization is enabled - * @return - */ - public boolean isRoamingCustomizationEnabled() { - return mRoamingCustomizationCarrierNameEnabled; - } - - /** - * Returns true if the current network for the subscription is considered roaming. - * It is considered roaming if the carrier of the sim card and network are not the same. - * @param subId the subscription ID. - */ - public boolean isRoaming(int subId) { - String simOperatorName = - mCarrierMap.getOrDefault(mTelephonyManager.getSimOperator(subId), ""); - String networkOperatorName = - mCarrierMap.getOrDefault(mTelephonyManager.getNetworkOperator(subId), ""); - if (DEBUG) { - Log.d(TAG, "isRoaming subId=" + subId - + " simOperator=" + mTelephonyManager.getSimOperator(subId) - + " networkOperator=" + mTelephonyManager.getNetworkOperator(subId)); - } - boolean roaming = false; - if (!TextUtils.isEmpty(simOperatorName) && !TextUtils.isEmpty(networkOperatorName) - && !simOperatorName.equals(networkOperatorName)) { - roaming = true; - } - - return roaming; - } - - /** - * Returns the roaming customization carrier name. - * @param subId the subscription ID. - */ - public String getRoamingCarrierName(int subId) { - String simOperatorName = - mCarrierMap.getOrDefault(mTelephonyManager.getSimOperator(subId), ""); - String networkOperatorName = - mCarrierMap.getOrDefault(mTelephonyManager.getNetworkOperator(subId), ""); - StringBuilder combinedCarrierName = new StringBuilder(); - combinedCarrierName.append(simOperatorName) - .append(mConnector) - .append(networkOperatorName); - return combinedCarrierName.toString(); - } - - public void loadCarrierMap(Context context) { - String customizationConfigs[] = - context.getResources().getStringArray(R.array.customization_carrier_name_list); - for(String config : customizationConfigs ) { - String[] kv = config.trim().split(":"); - if (kv.length != 2) { - Log.e(TAG, "invalid key value config " + config); - continue; - } - mCarrierMap.put(kv[0], kv[1]); - } - } -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index a4537267ed62..948cb5ee6b58 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -36,7 +36,10 @@ import com.android.systemui.plugins.PluginDependencyProvider; import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.qs.tiles.DndTile; +import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ExtensionController; +import com.android.systemui.tristate.TriStateUiController; +import com.android.systemui.tristate.TriStateUiControllerImpl; import com.android.systemui.tuner.TunerService; import java.io.PrintWriter; @@ -50,7 +53,7 @@ import javax.inject.Inject; */ @SysUISingleton public class VolumeDialogComponent implements VolumeComponent, TunerService.Tunable, - VolumeDialogControllerImpl.UserActivityListener{ + VolumeDialogControllerImpl.UserActivityListener, TriStateUiController.UserActivityListener { public static final String VOLUME_DOWN_SILENT = "sysui_volume_down_silent"; public static final String VOLUME_UP_SILENT = "sysui_volume_up_silent"; @@ -67,6 +70,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna protected final Context mContext; private final VolumeDialogControllerImpl mController; + private TriStateUiControllerImpl mTriStateController; private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_ASSETS_PATHS | ActivityInfo.CONFIG_UI_MODE); @@ -81,6 +85,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna KeyguardViewMediator keyguardViewMediator, ActivityStarter activityStarter, VolumeDialogControllerImpl volumeDialogController, + ConfigurationController configurationController, DemoModeController demoModeController, PluginDependencyProvider pluginDependencyProvider, ExtensionController extensionController, @@ -91,6 +96,8 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna mActivityStarter = activityStarter; mController = volumeDialogController; mController.setUserActivityListener(this); + boolean hasAlertSlider = mContext.getResources(). + getBoolean(com.android.internal.R.bool.config_hasAlertSlider); // Allow plugins to reference the VolumeDialogController. pluginDependencyProvider.allowPluginDependency(VolumeDialogController.class); extensionController.newExtension(VolumeDialog.class) @@ -102,6 +109,14 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna } mDialog = dialog; mDialog.init(LayoutParams.TYPE_VOLUME_OVERLAY, mVolumeDialogCallback); + if (hasAlertSlider) { + if (mTriStateController != null) { + mTriStateController.destroy(); + } + mTriStateController = new TriStateUiControllerImpl(mContext, + volumeDialogController, configurationController); + mTriStateController.init(LayoutParams.TYPE_VOLUME_OVERLAY, this); + } }).build(); @@ -202,6 +217,11 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna mActivityStarter.startActivity(intent, true /* onlyProvisioned */, true /* dismissShade */); } + @Override + public void onTriStateUserActivity() { + onUserActivity(); + } + private final VolumeDialogImpl.Callback mVolumeDialogCallback = new VolumeDialogImpl.Callback() { @Override public void onZenSettingsClicked() { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 93622200ad46..d83a9acb41ad 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -23,11 +23,13 @@ import static android.media.AudioManager.RINGER_MODE_VIBRATE; import static android.media.AudioManager.STREAM_ACCESSIBILITY; import static android.media.AudioManager.STREAM_ALARM; import static android.media.AudioManager.STREAM_MUSIC; +import static android.media.AudioManager.STREAM_NOTIFICATION; import static android.media.AudioManager.STREAM_RING; import static android.media.AudioManager.STREAM_VOICE_CALL; import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE; import static android.view.View.GONE; import static android.view.View.INVISIBLE; +import static android.view.View.LAYOUT_DIRECTION_LTR; import static android.view.View.LAYOUT_DIRECTION_RTL; import static android.view.View.VISIBLE; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; @@ -46,6 +48,8 @@ import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.Dialog; import android.app.KeyguardManager; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothProfile; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; @@ -66,6 +70,9 @@ import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.RotateDrawable; import android.media.AudioManager; import android.media.AudioSystem; +import android.media.session.MediaController; +import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; import android.os.Debug; import android.os.Handler; import android.os.Looper; @@ -76,6 +83,7 @@ import android.os.VibrationEffect; import android.provider.Settings; import android.provider.Settings.Global; import android.text.InputFilter; +import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.Slog; @@ -126,6 +134,7 @@ import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.plugins.VolumeDialogController.State; import com.android.systemui.plugins.VolumeDialogController.StreamState; +import com.android.systemui.statusbar.phone.ExpandableIndicator; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; @@ -243,6 +252,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private CaptionsToggleImageButton mODICaptionsIcon; private View mSettingsView; private ImageButton mSettingsIcon; + private View mExpandRowsView; + private ExpandableIndicator mExpandRows; private FrameLayout mZenIcon; private final List<VolumeRow> mRows = new ArrayList<>(); private ConfigurableTexts mConfigurableTexts; @@ -280,9 +291,21 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private Consumer<Boolean> mCrossWindowBlurEnabledListener; private BackgroundBlurDrawable mDialogRowsViewBackground; private final InteractionJankMonitor mInteractionJankMonitor; + private final boolean mVolumePanelOnLeft; private int mWindowGravity; + // Variable to track the default row with which the panel is initially shown + private VolumeRow mDefaultRow = null; + + private FrameLayout mRoundedBorderBottom; + + // Volume panel expand state + private boolean mExpanded; + + // Number of animating rows + private int mAnimatingRows = 0; + @VisibleForTesting final int mVolumeRingerIconDrawableId = R.drawable.ic_speaker_on; @VisibleForTesting @@ -335,6 +358,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mUseBackgroundBlur = mContext.getResources().getBoolean(R.bool.config_volumeDialogUseBackgroundBlur); mInteractionJankMonitor = interactionJankMonitor; + mVolumePanelOnLeft = + mContext.getResources().getBoolean(R.bool.config_audioPanelOnLeftSide); dumpManager.registerDumpable("VolumeDialogImpl", this); @@ -440,27 +465,75 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, final int[] locInWindow = new int[2]; view.getLocationInWindow(locInWindow); - float x = locInWindow[0]; - float y = locInWindow[1]; + float xExtraSize = 0; + float yExtraSize = 0; // The ringer and rows container has extra height at the top to fit the expanded ringer // drawer. This area should not be touchable unless the ringer drawer is open. // In landscape the ringer expands to the left and it has to be ensured that if there // are multiple rows they are touchable. - if (view == mTopContainer && !mIsRingerDrawerOpen) { + // The invisible expandable rows reserve space if the panel is not expanded, this space + // needs to be touchable. + if (view == mTopContainer) { if (!isLandscape()) { - y += getRingerDrawerOpenExtraSize(); - } else if (getRingerDrawerOpenExtraSize() > getVisibleRowsExtraSize()) { - x += (getRingerDrawerOpenExtraSize() - getVisibleRowsExtraSize()); + if (!mIsRingerDrawerOpen) { + yExtraSize = getRingerDrawerOpenExtraSize(); + } + if (!mExpanded) { + xExtraSize = getExpandableRowsExtraSize(); + } + } else { + if (!mIsRingerDrawerOpen && !mExpanded) { + xExtraSize = + Math.max(getRingerDrawerOpenExtraSize(), getExpandableRowsExtraSize()); + } else if (!mIsRingerDrawerOpen) { + if (getRingerDrawerOpenExtraSize() > getVisibleRowsExtraSize()) { + xExtraSize = getRingerDrawerOpenExtraSize() - getVisibleRowsExtraSize(); + } + } else if (!mExpanded) { + if ((getVisibleRowsExtraSize() + getExpandableRowsExtraSize()) + > getRingerDrawerOpenExtraSize()) { + xExtraSize = (getVisibleRowsExtraSize() + getExpandableRowsExtraSize()) + - getRingerDrawerOpenExtraSize(); + } + } } } - mTouchableRegion.op( - (int) x, - (int) y, - locInWindow[0] + view.getWidth(), - locInWindow[1] + view.getHeight(), - Region.Op.UNION); + if (isWindowGravityLeft()) { + mTouchableRegion.op( + locInWindow[0], + locInWindow[1] + (int) yExtraSize, + locInWindow[0] + view.getWidth() - (int) xExtraSize, + locInWindow[1] + view.getHeight(), + Region.Op.UNION); + } else { + mTouchableRegion.op( + locInWindow[0] + (int) xExtraSize, + locInWindow[1] + (int) yExtraSize, + locInWindow[0] + view.getWidth(), + locInWindow[1] + view.getHeight(), + Region.Op.UNION); + } + } + + // Helper to set gravity. + private void setGravity(ViewGroup viewGroup, int gravity) { + if (viewGroup instanceof LinearLayout) { + ((LinearLayout) viewGroup).setGravity(gravity); + } + } + + // Helper to set layout gravity. + private void setLayoutGravity(ViewGroup viewGroup, int gravity) { + if (viewGroup != null) { + Object obj = viewGroup.getLayoutParams(); + if (obj instanceof FrameLayout.LayoutParams) { + ((FrameLayout.LayoutParams) obj).gravity = gravity; + } else if (obj instanceof LinearLayout.LayoutParams) { + ((LinearLayout.LayoutParams) obj).gravity = gravity; + } + } } private void initDialog(int lockTaskModeState) { @@ -471,6 +544,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mConfigurableTexts = new ConfigurableTexts(mContext); mHovering = false; mShowing = false; + mExpanded = false; mWindow = mDialog.getWindow(); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); @@ -490,6 +564,11 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, lp.windowAnimations = -1; mOriginalGravity = mContext.getResources().getInteger(R.integer.volume_dialog_gravity); + if (!mShowActiveStreamOnly) { + // Clear the pre-defined gravity for left or right, this is handled by mVolumePanelOnLeft + mOriginalGravity &= ~(Gravity.LEFT | Gravity.RIGHT); + mOriginalGravity |= mVolumePanelOnLeft ? Gravity.LEFT : Gravity.RIGHT; + } mWindowGravity = Gravity.getAbsoluteGravity(mOriginalGravity, mContext.getResources().getConfiguration().getLayoutDirection()); lp.gravity = mWindowGravity; @@ -499,6 +578,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mDialog.setContentView(R.layout.volume_dialog); mDialogView = mDialog.findViewById(R.id.volume_dialog); mDialogView.setAlpha(0); + mDialogView.setLayoutDirection( + mVolumePanelOnLeft ? LAYOUT_DIRECTION_LTR : LAYOUT_DIRECTION_RTL); mDialog.setCanceledOnTouchOutside(true); mDialog.setOnShowListener(dialog -> { mDialogView.getViewTreeObserver().addOnComputeInternalInsetsListener(this); @@ -600,6 +681,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, updateBackgroundForDrawerClosedAmount(); setTopContainerBackgroundDrawable(); + + // Rows need to be updated after mRingerAndDrawerContainerBackground is set + updateRowsH(getActiveRow()); } }); } @@ -644,6 +728,32 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mSettingsView = mDialog.findViewById(R.id.settings_container); mSettingsIcon = mDialog.findViewById(R.id.settings); + mRoundedBorderBottom = mDialog.findViewById(R.id.rounded_border_bottom); + + mExpandRowsView = mDialog.findViewById(R.id.expandable_indicator_container); + mExpandRows = mDialog.findViewById(R.id.expandable_indicator); + + if (isWindowGravityLeft()) { + ViewGroup container = mDialog.findViewById(R.id.volume_dialog_container); + setGravity(container, Gravity.LEFT); + + setGravity(mDialogView, Gravity.LEFT); + + setGravity((ViewGroup) mTopContainer, Gravity.LEFT); + + setLayoutGravity(mRingerDrawerNewSelectionBg, Gravity.BOTTOM | Gravity.LEFT); + + setLayoutGravity(mSelectedRingerContainer, Gravity.BOTTOM | Gravity.LEFT); + + setGravity(mRinger, Gravity.LEFT); + + setGravity(mDialogRowsViewContainer, Gravity.LEFT); + + setGravity(mODICaptionsView, Gravity.LEFT); + + mExpandRows.setRotation(-90); + } + if (mRows.isEmpty()) { if (!AudioSystem.isSingleVolume(mContext)) { addRow(STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility, @@ -656,6 +766,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, addRow(AudioManager.STREAM_RING, R.drawable.ic_ring_volume, R.drawable.ic_ring_volume_off, true, false); + addRow(AudioManager.STREAM_NOTIFICATION, R.drawable.ic_notifications_alert, + R.drawable.ic_notifications_silence, true, false); addRow(STREAM_ALARM, R.drawable.ic_alarm, R.drawable.ic_volume_alarm_mute, true, false); @@ -717,10 +829,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, Configuration.ORIENTATION_LANDSCAPE; } - private boolean isRtl() { - return mContext.getResources().getConfiguration().getLayoutDirection() - == LAYOUT_DIRECTION_RTL; - } + private boolean isRtl() { return mDialogView.getLayoutDirection() == LAYOUT_DIRECTION_RTL; } public void setStreamImportant(int stream, boolean important) { mHandler.obtainMessage(H.SET_STREAM_IMPORTANT, stream, important ? 1 : 0).sendToTarget(); @@ -911,6 +1020,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mDialogView.getPaddingTop(), mDialogView.getPaddingRight(), mDialogView.getPaddingBottom() + getRingerDrawerOpenExtraSize()); + } else if (isWindowGravityLeft()) { + mDialogView.setPadding( + mDialogView.getPaddingLeft(), + mDialogView.getPaddingTop(), + mDialogView.getPaddingRight() + getRingerDrawerOpenExtraSize(), + mDialogView.getPaddingBottom()); } else { mDialogView.setPadding( mDialogView.getPaddingLeft() + getRingerDrawerOpenExtraSize(), @@ -980,15 +1095,16 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } /** - * Translation to apply form the origin (either top or left) to overlap the selection background - * with the given mode in the drawer. + * Translation to apply form the origin (either top or left/right) to overlap the selection + * background with the given mode in the drawer. */ private float getTranslationInDrawerForRingerMode(int mode) { - return mode == RINGER_MODE_VIBRATE - ? -mRingerDrawerItemSize * 2 - : mode == RINGER_MODE_SILENT - ? -mRingerDrawerItemSize - : 0; + final int distantRinger = ((isLandscape() && isWindowGravityLeft()) ? RINGER_MODE_NORMAL + : RINGER_MODE_VIBRATE); + return (mode == distantRinger ? mRingerDrawerItemSize * 2 + : mode == RINGER_MODE_SILENT ? mRingerDrawerItemSize + : 0) + * ((isLandscape() && isWindowGravityLeft()) ? 1 : -1); } /** Animates in the ringer drawer. */ @@ -1019,12 +1135,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, getTranslationInDrawerForRingerMode(mState.ringerModeInternal)); } - // Move the drawer so that the top/rightmost ringer choice overlaps with the selected ringer + // Move the drawer so that the top/outmost ringer choice overlaps with the selected ringer // icon. if (!isLandscape()) { mRingerDrawerContainer.setTranslationY(mRingerDrawerItemSize * (mRingerCount - 1)); } else { - mRingerDrawerContainer.setTranslationX(mRingerDrawerItemSize * (mRingerCount - 1)); + mRingerDrawerContainer.setTranslationX( + (isWindowGravityLeft() ? -1 : 1) * mRingerDrawerItemSize * (mRingerCount - 1)); } mRingerDrawerContainer.setAlpha(0f); mRingerDrawerContainer.setVisibility(VISIBLE); @@ -1106,7 +1223,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, .start(); } else { mRingerDrawerContainer.animate() - .translationX(mRingerDrawerItemSize * 2) + .translationX((isWindowGravityLeft() ? -1 : 1) * mRingerDrawerItemSize * 2) .start(); } @@ -1127,24 +1244,102 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mIsRingerDrawerOpen = false; } + /** + * Returns a {@link MediaController} that state is playing and type is local playback, + * and also have active sessions. + */ + @Nullable + private MediaController getActiveLocalMediaController() { + MediaSessionManager mediaSessionManager = + mContext.getSystemService(MediaSessionManager.class); + MediaController localController = null; + final List<String> remoteMediaSessionLists = new ArrayList<>(); + for (MediaController controller : mediaSessionManager.getActiveSessions(null)) { + final MediaController.PlaybackInfo pi = controller.getPlaybackInfo(); + if (pi == null) { + // do nothing + continue; + } + final PlaybackState playbackState = controller.getPlaybackState(); + if (playbackState == null) { + // do nothing + continue; + } + if (D.BUG) { + Log.d(TAG, + "getActiveLocalMediaController() package name : " + + controller.getPackageName() + + ", play back type : " + pi.getPlaybackType() + + ", play back state : " + playbackState.getState()); + } + if (playbackState.getState() != PlaybackState.STATE_PLAYING) { + // do nothing + continue; + } + if (pi.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { + if (localController != null + && TextUtils.equals( + localController.getPackageName(), controller.getPackageName())) { + localController = null; + } + if (!remoteMediaSessionLists.contains(controller.getPackageName())) { + remoteMediaSessionLists.add(controller.getPackageName()); + } + continue; + } + if (pi.getPlaybackType() == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) { + if (localController == null + && !remoteMediaSessionLists.contains(controller.getPackageName())) { + localController = controller; + } + } + } + return localController; + } + + private boolean isBluetoothA2dpConnected() { + final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() + && mBluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP) + == BluetoothProfile.STATE_CONNECTED; + } + + private boolean isMediaControllerAvailable() { + final MediaController mediaController = getActiveLocalMediaController(); + return mediaController != null && !TextUtils.isEmpty(mediaController.getPackageName()); + } + private void initSettingsH(int lockTaskModeState) { + final boolean showSettings = mDeviceProvisionedController.isCurrentUserSetup() + && lockTaskModeState == LOCK_TASK_MODE_NONE; + if (mRoundedBorderBottom != null) { + mRoundedBorderBottom.setVisibility(!showSettings ? VISIBLE : GONE); + } if (mSettingsView != null) { mSettingsView.setVisibility( - mDeviceProvisionedController.isCurrentUserSetup() && - lockTaskModeState == LOCK_TASK_MODE_NONE ? VISIBLE : GONE); + showSettings && (isMediaControllerAvailable() || isBluetoothA2dpConnected()) + ? VISIBLE + : GONE); } if (mSettingsIcon != null) { mSettingsIcon.setOnClickListener(v -> { Events.writeEvent(Events.EVENT_SETTINGS_CLICK); + String packageName = isMediaControllerAvailable() + ? getActiveLocalMediaController().getPackageName() + : ""; + mMediaOutputDialogFactory.create(packageName, true, mDialogView); dismissH(DISMISS_REASON_SETTINGS_CLICKED); - mMediaOutputDialogFactory.dismiss(); - if (FeatureFlagUtils.isEnabled(mContext, - FeatureFlagUtils.SETTINGS_VOLUME_PANEL_IN_SYSTEMUI)) { - mVolumePanelFactory.create(true /* aboveStatusBar */, null); - } else { - mActivityStarter.startActivity(new Intent(Settings.Panel.ACTION_VOLUME), - true /* dismissShade */); - } + }); + } + + if (mExpandRowsView != null) { + mExpandRowsView.setVisibility(showSettings ? VISIBLE : GONE); + } + if (mExpandRows != null) { + mExpandRows.setOnClickListener(v -> { + mExpanded = !mExpanded; + updateRowsH(mDefaultRow, true); + mExpandRows.setExpanded(mExpanded); }); } } @@ -1410,6 +1605,10 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mConfigChanged = false; } + if (mDefaultRow == null) { + mDefaultRow = getActiveRow(); + } + initSettingsH(lockTaskModeState); mShowing = true; mIsAnimatingDismiss = false; @@ -1471,6 +1670,10 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, protected void dismissH(int reason) { Trace.beginSection("VolumeDialogImpl#dismissH"); + // Avoid multiple animation calls on touch spams. + if (!mShowing) { + return; + } Log.i(TAG, "mDialog.dismiss() reason: " + Events.DISMISS_REASONS[reason] + " from: " + Debug.getCaller()); @@ -1511,6 +1714,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mDialog.dismiss(); } tryToRemoveCaptionsTooltip(); + mExpanded = false; + if (mExpandRows != null) { + mExpandRows.setExpanded(mExpanded); + } + mAnimatingRows = 0; + mDefaultRow = null; mIsAnimatingDismiss = false; hideRingerDrawer(); @@ -1538,6 +1747,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION); } + private boolean isExpandableRowH(VolumeRow row) { + return row != null && row != mDefaultRow && !row.defaultStream + && (row.stream == STREAM_RING + || row.stream == STREAM_NOTIFICATION + || row.stream == STREAM_ALARM + || row.stream == STREAM_MUSIC); + } private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) { boolean isActive = row.stream == activeRow.stream; @@ -1557,10 +1773,18 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, return true; } - if (row.defaultStream) { + if (mExpanded && isExpandableRowH(row)) { + return true; + } + + // if the row is the default stream or the row with which this panel was created, + // show it additonally to the active row if it is one of the following streams + if (row.defaultStream || mDefaultRow == row) { return activeRow.stream == STREAM_RING + || activeRow.stream == STREAM_NOTIFICATION || activeRow.stream == STREAM_ALARM || activeRow.stream == STREAM_VOICE_CALL + || activeRow.stream == STREAM_MUSIC || activeRow.stream == STREAM_ACCESSIBILITY || mDynamic.get(activeRow.stream); } @@ -1571,29 +1795,39 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private void updateRowsH(final VolumeRow activeRow) { Trace.beginSection("VolumeDialogImpl#updateRowsH"); + updateRowsH(activeRow, false); + } + + private void updateRowsH(final VolumeRow activeRow, boolean animate) { if (D.BUG) Log.d(TAG, "updateRowsH"); if (!mShowing) { trimObsoleteH(); } + boolean isOutmostIndexMax = isWindowGravityLeft() ? isRtl() : !isRtl(); + // Index of the last row that is actually visible. - int rightmostVisibleRowIndex = !isRtl() ? -1 : Short.MAX_VALUE; + int outmostVisibleRowIndex = isOutmostIndexMax ? -1 : Short.MAX_VALUE; // apply changes to all rows for (final VolumeRow row : mRows) { final boolean isActive = row == activeRow; + final boolean isExpandableRow = isExpandableRowH(row); final boolean shouldBeVisible = shouldBeVisibleH(row, activeRow); - Util.setVisOrGone(row.view, shouldBeVisible); - if (shouldBeVisible && mRingerAndDrawerContainerBackground != null) { - // For RTL, the rightmost row has the lowest index since child views are laid out + if (!isExpandableRow) { + Util.setVisOrGone(row.view, shouldBeVisible); + } else if (!mExpanded) { + row.view.setVisibility(View.INVISIBLE); + } + + if ((shouldBeVisible || isExpandableRow) + && mRingerAndDrawerContainerBackground != null) { + // For RTL, the outmost row has the lowest index since child views are laid out // from right to left. - rightmostVisibleRowIndex = - !isRtl() - ? Math.max(rightmostVisibleRowIndex, - mDialogRowsView.indexOfChild(row.view)) - : Math.min(rightmostVisibleRowIndex, - mDialogRowsView.indexOfChild(row.view)); + outmostVisibleRowIndex = isOutmostIndexMax + ? Math.max(outmostVisibleRowIndex, mDialogRowsView.indexOfChild(row.view)) + : Math.min(outmostVisibleRowIndex, mDialogRowsView.indexOfChild(row.view)); // Add spacing between each of the visible rows - we'll remove the spacing from the // last row after the loop. @@ -1601,12 +1835,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, if (layoutParams instanceof LinearLayout.LayoutParams) { final LinearLayout.LayoutParams linearLayoutParams = ((LinearLayout.LayoutParams) layoutParams); - if (!isRtl()) { + if (isOutmostIndexMax) { linearLayoutParams.setMarginEnd(mRingerRowsPadding); } else { linearLayoutParams.setMarginStart(mRingerRowsPadding); } } + row.view.setLayoutParams(layoutParams); // Set the background on each of the rows. We'll remove this from the last row after // the loop, since the last row's background is drawn by the main volume container. @@ -1614,13 +1849,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mContext.getDrawable(R.drawable.volume_row_rounded_background)); } - if (row.view.isShown()) { + if (row.view.isShown() || isExpandableRow) { updateVolumeRowTintH(row, isActive); } } - if (rightmostVisibleRowIndex > -1 && rightmostVisibleRowIndex < Short.MAX_VALUE) { - final View lastVisibleChild = mDialogRowsView.getChildAt(rightmostVisibleRowIndex); + if (outmostVisibleRowIndex > -1 && outmostVisibleRowIndex < Short.MAX_VALUE) { + final View lastVisibleChild = mDialogRowsView.getChildAt(outmostVisibleRowIndex); final ViewGroup.LayoutParams layoutParams = lastVisibleChild.getLayoutParams(); // Remove the spacing on the last row, and remove its background since the container is // drawing a background for this row. @@ -1629,8 +1864,106 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, ((LinearLayout.LayoutParams) layoutParams); linearLayoutParams.setMarginStart(0); linearLayoutParams.setMarginEnd(0); + lastVisibleChild.setLayoutParams(linearLayoutParams); lastVisibleChild.setBackgroundColor(Color.TRANSPARENT); } + + int elevationCount = 0; + if (animate) { + // Increase the elevation of the outmost row so that other rows animate behind it. + lastVisibleChild.setElevation(1f / ++elevationCount); + + // Add a solid background to the outmost row temporary so that other rows animate + // behind it + lastVisibleChild.setBackgroundDrawable( + mContext.getDrawable(R.drawable.volume_background)); + } + + int[] lastVisibleChildLocation = new int[2]; + lastVisibleChild.getLocationInWindow(lastVisibleChildLocation); + + // Track previous rows to calculate translations + int visibleRowsCount = 0; + int hiddenRowsCount = 0; + int rowWidth = mDialogWidth + mRingerRowsPadding; + + for (final VolumeRow row : mRows) { + final boolean isExpandableRow = isExpandableRowH(row); + final boolean shouldBeVisible = shouldBeVisibleH(row, activeRow); + + if (shouldBeVisible) { + visibleRowsCount++; + } else if (isExpandableRow) { + hiddenRowsCount++; + } + + // Only move rows that are either expandable or visible and not the default stream + if ((!isExpandableRow && !shouldBeVisible) || row.defaultStream) { + continue; + } + + // Cancel any ongoing animations + row.view.animate().cancel(); + + // Expandable rows need to animate behind the last visible row, an additional + // always visible stream animates next to the default stream + float translationX = (isWindowGravityLeft() ? -1 : 1) * hiddenRowsCount * rowWidth; + + if (animate) { + // If the translation is not set and the panel is expanding start the + // animation behind the main row + if (isExpandableRow && mExpanded && row.view.getTranslationX() == 0f) { + row.view.setTranslationX( + (isWindowGravityLeft() ? -1 : 1) * visibleRowsCount * rowWidth); + } + + // The elevation should decrease from the outmost row to the inner rows, so that + // every row animates behind the outer rows + row.view.setElevation(1f / ++elevationCount); + + row.view.setVisibility(View.VISIBLE); + + // Track how many rows are animating to avoid running animation end actions + // if there is still a row animating + mAnimatingRows++; + row.view.animate() + .translationX(translationX) + .setDuration(mExpanded ? mDialogShowAnimationDurationMs + : mDialogHideAnimationDurationMs) + .setInterpolator(mExpanded + ? new SystemUIInterpolators.LogDecelerateInterpolator() + : new SystemUIInterpolators.LogAccelerateInterpolator()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + mAnimatingRows--; + animation.removeAllListeners(); + } + + @Override + public void onAnimationEnd(Animator animation) { + row.view.setElevation(0); + if (!shouldBeVisible) { + row.view.setVisibility(View.INVISIBLE); + } + mAnimatingRows--; + if (mAnimatingRows == 0) { + // Restore the elevation and background + lastVisibleChild.setElevation(0); + lastVisibleChild.setBackgroundColor(Color.TRANSPARENT); + // Set the active stream to ensure the volume keys change + // the volume of the tinted row. The tint was set before + // already, but setting the active row cancels ongoing + // animations. + mController.setActiveStream(activeRow.stream); + } + } + }); + } else { + row.view.setTranslationX(translationX); + row.view.setVisibility(shouldBeVisible ? View.VISIBLE : View.INVISIBLE); + } + } } updateBackgroundForDrawerClosedAmount(); @@ -1753,7 +2086,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, protected void onStateChangedH(State state) { if (D.BUG) Log.d(TAG, "onStateChangedH() state: " + state.toString()); - if (mState != null && state != null + if (mShowing && mState != null && state != null && mState.ringerModeInternal != -1 && mState.ringerModeInternal != state.ringerModeInternal && state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) { @@ -1806,6 +2139,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, final boolean isVoiceCallStream = row.stream == AudioManager.STREAM_VOICE_CALL; final boolean isA11yStream = row.stream == STREAM_ACCESSIBILITY; final boolean isRingStream = row.stream == AudioManager.STREAM_RING; + final boolean isNotificationStream = row.stream == AudioManager.STREAM_NOTIFICATION; final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM; final boolean isAlarmStream = row.stream == STREAM_ALARM; final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC; @@ -1813,6 +2147,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; final boolean isRingSilent = isRingStream && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT; + final boolean isNotificationMuted = isNotificationStream && ss.muted; final boolean isZenPriorityOnly = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS; final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; @@ -1845,7 +2180,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, final int iconRes; if (isRingVibrate) { iconRes = R.drawable.ic_volume_ringer_vibrate; - } else if (isRingSilent || zenMuted) { + } else if (isRingSilent || isNotificationMuted || zenMuted) { iconRes = row.iconMuteRes; } else if (ss.routedToBluetooth) { if (isVoiceCallStream) { @@ -2149,6 +2484,21 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, return (visibleRows - 1) * (mDialogWidth + mRingerRowsPadding); } + /** + * Return the size of invisible rows. + * Expandable rows are invisible while the panel is not expanded. + */ + private int getExpandableRowsExtraSize() { + VolumeRow activeRow = getActiveRow(); + int expandableRows = 0; + for (final VolumeRow row : mRows) { + if (isExpandableRowH(row)) { + expandableRows++; + } + } + return expandableRows * (mDialogWidth + mRingerRowsPadding); + } + private void updateBackgroundForDrawerClosedAmount() { if (mRingerAndDrawerContainerBackground == null) { return; @@ -2157,6 +2507,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, final Rect bounds = mRingerAndDrawerContainerBackground.copyBounds(); if (!isLandscape()) { bounds.top = (int) (mRingerDrawerClosedAmount * getRingerDrawerOpenExtraSize()); + } else if (isWindowGravityLeft()) { + bounds.right = (int) ((mDialogCornerRadius / 2) + mRingerDrawerItemSize + + (1f - mRingerDrawerClosedAmount) * getRingerDrawerOpenExtraSize()); } else { bounds.left = (int) (mRingerDrawerClosedAmount * getRingerDrawerOpenExtraSize()); } @@ -2164,7 +2517,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } /* - * The top container is responsible for drawing the solid color background behind the rightmost + * The top container is responsible for drawing the solid color background behind the outmost * (primary) volume row. This is because the volume drawer animates in from below, initially * overlapping the primary row. We need the drawer to draw below the row's SeekBar, since it * looks strange to overlap it, but above the row's background color, since otherwise it will be @@ -2198,8 +2551,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, ? mDialogRowsViewContainer.getTop() : mDialogRowsViewContainer.getTop() - mDialogCornerRadius); - // Set gravity to top-right, since additional rows will be added on the left. - background.setLayerGravity(0, Gravity.TOP | Gravity.RIGHT); + // Set gravity to top and opposite side where additional rows will be added. + background.setLayerGravity( + 0, isWindowGravityLeft() ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT); // In landscape, the ringer drawer animates out to the left (instead of down). Since the // drawer comes from the right (beyond the bounds of the dialog), we should clip it so it @@ -2248,7 +2602,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onLayoutDirectionChanged(int layoutDirection) { - mDialogView.setLayoutDirection(layoutDirection); } @Override @@ -2380,9 +2733,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public boolean onTouchEvent(@NonNull MotionEvent event) { if (mShowing) { - if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { - dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE); - return true; + switch(event.getAction()){ + case MotionEvent.ACTION_OUTSIDE: + case MotionEvent.ACTION_DOWN: + // Touches inside won't trigger onTouchEvent + dismissH(Events.DISMISS_REASON_TOUCH_OUTSIDE); + return false; } } return false; diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt index 38372a33f1e6..044ece8ea158 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt @@ -133,16 +133,6 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() { verify(coordinator).bouncerOrRun(action) verify(activityStarter).dismissKeyguardThenExecute(any(), any(), anyBoolean()) verify(action, never()).invoke() - - // Simulate a refresh call from a Publisher, which will trigger a call to runPendingAction - reset(action) - coordinator.runPendingAction(ID) - verify(action, never()).invoke() - - `when`(keyguardStateController.isUnlocked()).thenReturn(true) - reset(action) - coordinator.runPendingAction(ID) - verify(action).invoke() } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java index 4e9ec90199a2..74f950f6681a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java @@ -614,7 +614,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase { mKeyguardInteractor, mActivityStarter, mEmergencyButtonControllerFactory, - mKeyguardFaceAuthInteractor); + mKeyguardFaceAuthInteractor, + mTunerService); mNotificationPanelViewController.initDependencies( mCentralSurfaces, null, diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk index a41d0e57cd21..af19694cf6c0 100644 --- a/packages/overlays/Android.mk +++ b/packages/overlays/Android.mk @@ -25,7 +25,6 @@ LOCAL_REQUIRED_MODULES := \ DisplayCutoutEmulationHoleOverlay \ DisplayCutoutEmulationTallOverlay \ DisplayCutoutEmulationWaterfallOverlay \ - FontNotoSerifSourceOverlay \ NavigationBarMode3ButtonOverlay \ NavigationBarModeGesturalOverlay \ NavigationBarModeGesturalOverlayNarrowBack \ diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index ced97cc0b39e..e57dd26f06ae 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -7438,5 +7438,8 @@ message MetricsEvent { // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS + + // ICE Metrics + ICE = 2772; } } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java index 7d8bb51ff586..4e732e39a21e 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java @@ -96,7 +96,7 @@ public class AppWidgetXmlUtil { 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, Build.VERSION.INCREMENTAL); } /** @@ -107,7 +107,7 @@ public class AppWidgetXmlUtil { @NonNull final TypedXmlPullParser parser) { Objects.requireNonNull(parser); final String fingerprint = parser.getAttributeValue(null, ATTR_OS_FINGERPRINT); - if (!Build.FINGERPRINT.equals(fingerprint)) { + if (!Build.VERSION.INCREMENTAL.equals(fingerprint)) { return null; } final AppWidgetProviderInfo info = new AppWidgetProviderInfo(); diff --git a/services/core/Android.bp b/services/core/Android.bp index ad7faf3e2fcd..3db2c67bd171 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -189,9 +189,6 @@ java_library_static { "com.android.sysprop.watchdog", "ImmutabilityAnnotation", "securebox", - "vendor.qti.hardware.servicetracker-V1.0-java", - "vendor.qti.hardware.servicetracker-V1.2-java", - "vendor.qti.hardware.servicetrackeraidl-V1-java", ], javac_shard_size: 50, javacflags: [ diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index d94f4f22f2c9..fe65eec64633 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -172,6 +172,9 @@ public final class BatteryService extends SystemService { private boolean mBatteryLevelLow; + private boolean mOemFastCharger; + private boolean mLastOemFastCharger; + private long mDischargeStartTime; private int mDischargeStartLevel; @@ -515,6 +518,8 @@ public final class BatteryService extends SystemService { shutdownIfNoPowerLocked(); shutdownIfOverTempLocked(); + mOemFastCharger = isOemFastCharger(); + if (force || (mHealthInfo.batteryStatus != mLastBatteryStatus || mHealthInfo.batteryHealth != mLastBatteryHealth @@ -528,7 +533,8 @@ public final class BatteryService extends SystemService { || mHealthInfo.batteryChargeCounterUah != mLastChargeCounter || mInvalidCharger != mLastInvalidCharger || mHealthInfo.batteryCycleCount != mLastBatteryCycleCount - || mHealthInfo.chargingState != mLastCharingState)) { + || mHealthInfo.chargingState != mLastCharingState + || mOemFastCharger != mLastOemFastCharger)) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { @@ -712,6 +718,7 @@ public final class BatteryService extends SystemService { mLastInvalidCharger = mInvalidCharger; mLastBatteryCycleCount = mHealthInfo.batteryCycleCount; mLastCharingState = mHealthInfo.chargingState; + mLastOemFastCharger = mOemFastCharger; } } @@ -745,9 +752,11 @@ public final class BatteryService extends SystemService { intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounterUah); intent.putExtra(BatteryManager.EXTRA_CYCLE_COUNT, mHealthInfo.batteryCycleCount); intent.putExtra(BatteryManager.EXTRA_CHARGING_STATUS, mHealthInfo.chargingState); + intent.putExtra(BatteryManager.EXTRA_OEM_FAST_CHARGER, mOemFastCharger); if (DEBUG) { Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE - + ", info:" + mHealthInfo.toString()); + + ", info:" + mHealthInfo.toString() + + ", mOemFastCharger:" + mOemFastCharger); } mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, AppOpsManager.OP_NONE, @@ -802,6 +811,25 @@ public final class BatteryService extends SystemService { mLastBatteryLevelChangedSentMs = SystemClock.elapsedRealtime(); } + private boolean isOemFastCharger() { + final String path = mContext.getResources().getString( + com.android.internal.R.string.config_oemFastChargerStatusPath); + + if (path.isEmpty()) + return false; + + final String value = mContext.getResources().getString( + com.android.internal.R.string.config_oemFastChargerStatusValue); + + try { + return FileUtils.readTextFile(new File(path), value.length(), null).equals(value); + } catch (IOException e) { + Slog.e(TAG, "Failed to read oem fast charger status path: " + path); + } + + return false; + } + // TODO: Current code doesn't work since "--unplugged" flag in BSS was purposefully removed. private void logBatteryStatsLocked() { IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 6908a84c5841..fe21ed95317b 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -255,10 +255,6 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; -import vendor.qti.hardware.servicetracker.V1_0.IServicetracker; -import vendor.qti.hardware.servicetracker.V1_0.ServiceData; -import vendor.qti.hardware.servicetracker.V1_0.ClientData; - public final class ActiveServices { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM; private static final String TAG_MU = TAG + POSTFIX_MU; @@ -272,10 +268,6 @@ public final class ActiveServices { private static final boolean LOG_SERVICE_START_STOP = DEBUG_SERVICE; - private static final String AIDL_SERVICE = - "vendor.qti.hardware.servicetrackeraidl.IServicetracker/default"; - - private static boolean mIsAIDLSupported = true; // Foreground service types that always get immediate notification display, // expressed in the same bitmask format that ServiceRecord.foregroundServiceType // uses. @@ -415,12 +407,6 @@ public final class ActiveServices { /** Amount of time to allow a last ANR message to exist before freeing the memory. */ static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours - private vendor.qti.hardware.servicetracker.V1_0.IServicetracker mServicetracker; - private vendor.qti.hardware.servicetrackeraidl.IServicetracker mServicetracker_aidl; - - private final boolean isLowRamDevice = - SystemProperties.getBoolean("ro.config.low_ram", false); - String mLastAnrDump; AppWidgetManagerInternal mAppWidgetManagerInternal; @@ -683,15 +669,6 @@ public final class ActiveServices { SERVICE_RESCHEDULE = Boolean.parseBoolean(mPerf.perfGetProp("ro.vendor.qti.am.reschedule_service", "false")); this.mFGSLogger = new ForegroundServiceTypeLoggerModule(); - try { - if (ServiceManager.isDeclared(AIDL_SERVICE)){ - if (DEBUG_SERVICE) Slog.w(TAG, "AIDL is supported"); - mIsAIDLSupported = true; - } - } catch (Exception e) { - if (DEBUG_SERVICE) Slog.w(TAG, "AIDL not Supported"); - mIsAIDLSupported = false; - } } void systemServicesReady() { @@ -722,47 +699,6 @@ public final class ActiveServices { } } - private boolean getServicetrackerInstance() { - if (mServicetracker == null ) { - try { - mServicetracker = IServicetracker.getService(false); - } catch (java.util.NoSuchElementException e) { - // Service doesn't exist or cannot be opened logged below - } catch (RemoteException e) { - if (DEBUG_SERVICE) Slog.e(TAG, "Failed to get servicetracker interface", e); - return false; - } - if (mServicetracker == null) { - if (DEBUG_SERVICE) Slog.w(TAG, "servicetracker HIDL not available"); - return false; - } - } - return true; - } - - private boolean getAIDLServicetrackerInstance() { - - if (!mIsAIDLSupported) return false; - - if (mServicetracker_aidl == null ) { - try { - IBinder mBinder = ServiceManager.getService(AIDL_SERVICE); - mServicetracker_aidl = - vendor.qti.hardware.servicetrackeraidl.IServicetracker.Stub.asInterface(mBinder); - } catch (java.util.NoSuchElementException e) { - // Service doesn't exist or cannot be opened logged below - } catch (Exception e) { - if (DEBUG_SERVICE) Slog.e(TAG, "Failed to get servicetracker AIDL interface", e); - return false; - } - if (mServicetracker_aidl == null) { - if (DEBUG_SERVICE) Slog.w(TAG, "servicetracker AIDL not available"); - return false; - } - } - return true; - } - ServiceRecord getServiceByNameLocked(ComponentName name, int callingUser) { // TODO: Deal with global services if (DEBUG_MU) @@ -3582,80 +3518,6 @@ public final class ActiveServices { return false; } - private void getServiceTrackerAidlData(vendor.qti.hardware.servicetrackeraidl.ServiceData sData, - vendor.qti.hardware.servicetrackeraidl.ClientData cData, ServiceRecord r, - ConnectionRecord connrec, ProcessRecord callerApp, boolean unbind) { - if (unbind){ - sData.packageName = connrec.binding.service.packageName; - sData.processName = connrec.binding.service.shortInstanceName; - sData.lastActivity = connrec.binding.service.lastActivity; - if (connrec.binding.service.app != null) { - sData.pid = connrec.binding.service.app.getPid(); - sData.serviceB = connrec.binding.service.app.mState.isServiceB(); - } else { - sData.pid = -1; - sData.serviceB = false; - } - if (cData != null) { - cData.processName = connrec.binding.client.processName; - cData.pid = connrec.binding.client.getPid(); - } - return; - } - - sData.packageName = r.packageName; - sData.processName = r.shortInstanceName; - sData.lastActivity = r.lastActivity; - if (r.app != null) { - sData.pid = r.app.getPid(); - sData.serviceB = r.app.mState.isServiceB(); - } else { - sData.pid = -1; - sData.serviceB = false; - } - if (cData != null) { - cData.processName = callerApp.processName; - cData.pid = callerApp.getPid(); - } - } - - private void getServiceTrackerHidlData(vendor.qti.hardware.servicetracker.V1_0.ServiceData sData, - vendor.qti.hardware.servicetracker.V1_0.ClientData cData, - ServiceRecord r, ConnectionRecord connrec, ProcessRecord callerApp, boolean unbind) { - if (unbind) { - sData.packageName = connrec.binding.service.packageName; - sData.processName = connrec.binding.service.shortInstanceName; - sData.lastActivity = connrec.binding.service.lastActivity; - if (connrec.binding.service.app != null) { - sData.pid = connrec.binding.service.app.getPid(); - sData.serviceB = connrec.binding.service.app.mState.isServiceB(); - } else { - sData.pid = -1; - sData.serviceB = false; - } - if (cData != null) { - cData.processName = connrec.binding.client.processName; - cData.pid = connrec.binding.client.getPid(); - } - return; - } - - sData.packageName = r.packageName; - sData.processName = r.shortInstanceName; - sData.lastActivity = r.lastActivity; - if (r.app != null) { - sData.pid = r.app.getPid(); - sData.serviceB = r.app.mState.isServiceB(); - } else { - sData.pid = -1; - sData.serviceB = false; - } - if (cData != null) { - cData.processName = callerApp.processName; - cData.pid = callerApp.getPid(); - } - } - int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, long flags, String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid, @@ -3881,30 +3743,6 @@ public final class ActiveServices { } clist.add(c); - if (!isLowRamDevice) { - try { - if (getAIDLServicetrackerInstance()) { - vendor.qti.hardware.servicetrackeraidl.ServiceData sData = - new vendor.qti.hardware.servicetrackeraidl.ServiceData(); - vendor.qti.hardware.servicetrackeraidl.ClientData cData = - new vendor.qti.hardware.servicetrackeraidl.ClientData(); - getServiceTrackerAidlData(sData, cData, s, null, callerApp, false); - mServicetracker_aidl.bindService(sData, cData); - } else if (getServicetrackerInstance()) { - vendor.qti.hardware.servicetracker.V1_0.ServiceData sData = - new vendor.qti.hardware.servicetracker.V1_0.ServiceData(); - vendor.qti.hardware.servicetracker.V1_0.ClientData cData = - new vendor.qti.hardware.servicetracker.V1_0.ClientData(); - getServiceTrackerHidlData(sData, cData, s, null, callerApp, false); - mServicetracker.bindService(sData, cData); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send bind details to servicetracker HAL", e); - mServicetracker = null; - mServicetracker_aidl = null; - } - } - boolean needOomAdj = false; if (c.hasFlag(Context.BIND_AUTO_CREATE)) { s.lastActivity = SystemClock.uptimeMillis(); @@ -4141,29 +3979,6 @@ public final class ActiveServices { while (clist.size() > 0) { ConnectionRecord r = clist.get(0); - if (!isLowRamDevice) { - try { - if (getAIDLServicetrackerInstance()) { - vendor.qti.hardware.servicetrackeraidl.ServiceData sData = - new vendor.qti.hardware.servicetrackeraidl.ServiceData(); - vendor.qti.hardware.servicetrackeraidl.ClientData cData = - new vendor.qti.hardware.servicetrackeraidl.ClientData(); - getServiceTrackerAidlData(sData, cData, null, r, null, true); - mServicetracker_aidl.unbindService(sData, cData); - } else if (getServicetrackerInstance()) { - vendor.qti.hardware.servicetracker.V1_0.ServiceData sData = - new vendor.qti.hardware.servicetracker.V1_0.ServiceData(); - vendor.qti.hardware.servicetracker.V1_0.ClientData cData = - new vendor.qti.hardware.servicetracker.V1_0.ClientData(); - getServiceTrackerHidlData(sData, cData, null, r, null, true); - mServicetracker.unbindService(sData, cData); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send unbind details to servicetracker AIDL/HAL", e); - mServicetracker = null; - mServicetracker_aidl = null; - } - } removeConnectionLocked(r, null, null, true); if (clist.size() > 0 && clist.get(0) == r) { // In case it didn't get removed above, do it now. @@ -5597,26 +5412,6 @@ public final class ActiveServices { app.mState.getReportedProcState()); r.postNotification(false); created = true; - - if (!isLowRamDevice) { - try { - if (getAIDLServicetrackerInstance()) { - vendor.qti.hardware.servicetrackeraidl.ServiceData sData = - new vendor.qti.hardware.servicetrackeraidl.ServiceData(); - getServiceTrackerAidlData(sData, null, r, null, null, false); - mServicetracker_aidl.startService(sData); - } else if (getServicetrackerInstance()) { - vendor.qti.hardware.servicetracker.V1_0.ServiceData sData = - new vendor.qti.hardware.servicetracker.V1_0.ServiceData(); - getServiceTrackerHidlData(sData, null, r, null, null, false); - mServicetracker.startService(sData); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send start details to servicetracker HAL", e); - mServicetracker = null; - mServicetracker_aidl = null; - } - } } catch (DeadObjectException e) { Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app, "Died when creating service"); @@ -5820,25 +5615,6 @@ public final class ActiveServices { private void bringDownServiceLocked(ServiceRecord r, boolean enqueueOomAdj) { //Slog.i(TAG, "Bring down service:"); //r.dump(" "); - if (!isLowRamDevice) { - try { - if (getAIDLServicetrackerInstance()) { - vendor.qti.hardware.servicetrackeraidl.ServiceData sData = - new vendor.qti.hardware.servicetrackeraidl.ServiceData(); - getServiceTrackerAidlData(sData, null, r, null, null, false); - mServicetracker_aidl.destroyService(sData); - } else if (getServicetrackerInstance()) { - vendor.qti.hardware.servicetracker.V1_0.ServiceData sData = - new vendor.qti.hardware.servicetracker.V1_0.ServiceData(); - getServiceTrackerHidlData(sData, null, r, null, null, false); - mServicetracker.destroyService(sData); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send destroy details to servicetracker HAL", e); - mServicetracker = null; - mServicetracker_aidl = null; - } - } if (r.isShortFgs()) { // FGS can be stopped without the app calling stopService() or stopSelf(), // due to force-app-standby, or from Task Manager. @@ -6725,18 +6501,6 @@ public final class ActiveServices { } } - try { - if (!isLowRamDevice && getAIDLServicetrackerInstance()) { - mServicetracker_aidl.killProcess(app.getPid()); - } else if (!isLowRamDevice && getServicetrackerInstance()) { - mServicetracker.killProcess(app.getPid()); - } - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send kill process details to servicetracker AIDL/HAL", e); - mServicetracker = null; - mServicetracker_aidl = null; - } - // Clean up any connections this application has to other services. for (int i = psr.numberOfConnections() - 1; i >= 0; i--) { ConnectionRecord r = psr.getConnectionAt(i); diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index ed5c1306733e..fbf713d7d091 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -1842,9 +1842,17 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mContext.getSystemService(Context.TELEPHONY_SERVICE); int type = AGPS_SETID_TYPE_NONE; String setId = null; + final Boolean isEmergency = mNIHandler.getInEmergency(); + + // Unless we are in an emergency, do not provide sensitive subscriber information + // to SUPL servers. + if (!isEmergency) { + mGnssNative.setAgpsSetId(type, ""); + return; + } int subId = SubscriptionManager.getDefaultDataSubscriptionId(); - if (mGnssConfiguration.isActiveSimEmergencySuplEnabled() && mNIHandler.getInEmergency() + if (mGnssConfiguration.isActiveSimEmergencySuplEnabled() && isEmergency && mNetworkConnectivityHandler.getActiveSubId() >= 0) { subId = mNetworkConnectivityHandler.getActiveSubId(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 47f7b3ad99b3..9ba011ff9f8f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -909,6 +909,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService private final PackageProperty mPackageProperty = new PackageProperty(); + ArrayList<ComponentName> mDisabledComponentsList; + final PendingPackageBroadcasts mPendingBroadcasts; static final int SEND_PENDING_BROADCAST = 1; @@ -2270,6 +2272,20 @@ public class PackageManagerService implements PackageSender, TestUtilityService // Defer the app data fixup until we are done with app data clearing above. mPrepareAppDataFuture = mAppDataHelper.fixAppsDataOnBoot(); + // Disable components marked for disabling at build-time + mDisabledComponentsList = new ArrayList<ComponentName>(); + enableComponents(mContext.getResources().getStringArray( + com.android.internal.R.array.config_deviceDisabledComponents), + false); + enableComponents(mContext.getResources().getStringArray( + com.android.internal.R.array.config_globallyDisabledComponents), + false); + + // Enable components marked for forced-enable at build-time + enableComponents(mContext.getResources().getStringArray( + com.android.internal.R.array.config_forceEnabledComponents), + true); + // Legacy existing (installed before Q) non-system apps to hide // their icons in launcher. if (mIsPreQUpgrade) { @@ -2433,6 +2449,29 @@ public class PackageManagerService implements PackageSender, TestUtilityService Slog.i(TAG, "Fix for b/169414761 is applied"); } + private void enableComponents(String[] components, boolean enable) { + // Disable or enable components marked at build-time + for (String name : components) { + ComponentName cn = ComponentName.unflattenFromString(name); + if (!enable) { + mDisabledComponentsList.add(cn); + } + Slog.v(TAG, "Changing enabled state of " + name + " to " + enable); + String className = cn.getClassName(); + PackageSetting pkgSetting = mSettings.mPackages.get(cn.getPackageName()); + if (pkgSetting == null || pkgSetting.getPkg() == null + || !AndroidPackageUtils.hasComponentClassName(pkgSetting.getPkg(), className)) { + Slog.w(TAG, "Unable to change enabled state of " + name + " to " + enable); + continue; + } + if (enable) { + pkgSetting.enableComponentLPw(className, UserHandle.USER_OWNER); + } else { + pkgSetting.disableComponentLPw(className, UserHandle.USER_OWNER); + } + } + } + @GuardedBy("mLock") void updateInstantAppInstallerLocked(String modifiedPackage) { // we're only interested in updating the installer application when 1) it's not @@ -3856,6 +3895,14 @@ public class PackageManagerService implements PackageSender, TestUtilityService final int targetSize = settings.size(); for (int i = 0; i < targetSize; i++) { final int newState = settings.get(i).getEnabledState(); + if (settings.get(i).isComponent()) { + // Don't allow to enable components marked for disabling at build-time + if (mDisabledComponentsList.contains(settings.get(i).getComponentName())) { + Slog.d(TAG, "Ignoring attempt to set enabled state of disabled component " + + settings.get(i).getComponentName().flattenToString()); + return; + } + } if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT || newState == COMPONENT_ENABLED_STATE_ENABLED || newState == COMPONENT_ENABLED_STATE_DISABLED diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index db997d8d1d79..cfe9b681d734 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -1475,8 +1475,6 @@ public class PackageManagerServiceUtils { // 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."); - // 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, @@ -1484,6 +1482,7 @@ public class PackageManagerServiceUtils { 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); } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index aaf13ebeff2a..d5a891c4df77 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -463,7 +463,7 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile public void forceCurrent() { sdkVersion = Build.VERSION.SDK_INT; databaseVersion = CURRENT_DATABASE_VERSION; - buildFingerprint = Build.FINGERPRINT; + buildFingerprint = Build.VERSION.INCREMENTAL; 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 c6aba2ab9cbe..1aad29efa322 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -5206,7 +5206,7 @@ public class ShortcutService extends IShortcutService.Stub { // Injection point. String injectBuildFingerprint() { - return Build.FINGERPRINT; + return Build.VERSION.INCREMENTAL; } 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 4517b56f1245..6dc852714bdf 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -200,6 +200,7 @@ import com.android.internal.app.AssistUtils; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; +import com.android.internal.os.DeviceKeyHandler; import com.android.internal.os.RoSystemProperties; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.policy.IShortcutService; @@ -235,11 +236,15 @@ import com.android.server.wm.DisplayRotation; import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.AppTransitionListener; +import dalvik.system.PathClassLoader; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; +import java.lang.reflect.Constructor; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -638,6 +643,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int mCurrentUserId; + private AssistUtils mAssistUtils; + // Maps global key codes to the components that will handle them. private GlobalKeyManager mGlobalKeyManager; @@ -661,6 +668,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Timeout for showing the keyguard after the screen is on, in case no "ready" is received. private int mKeyguardDrawnTimeout = 1000; + private final List<DeviceKeyHandler> mDeviceKeyHandlers = new ArrayList<>(); + private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; @@ -1365,6 +1374,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private boolean hasAssistant() { + return mAssistUtils.getAssistComponentForUser(mCurrentUserId) != null; + } + private int getResolvedLongPressOnPowerBehavior() { if (FactoryTest.isLongPressOnPowerOffEnabled()) { return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; @@ -1372,7 +1385,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // If the config indicates the assistant behavior but the device isn't yet provisioned, show // global actions instead. - if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_ASSISTANT && !isDeviceProvisioned()) { + if (mLongPressOnPowerBehavior == LONG_PRESS_POWER_ASSISTANT && + (!isDeviceProvisioned() || !hasAssistant())) { return LONG_PRESS_POWER_GLOBAL_ACTIONS; } @@ -2230,6 +2244,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_safeModeEnabledVibePattern); + mAssistUtils = new AssistUtils(mContext); + mGlobalKeyManager = new GlobalKeyManager(mContext); // Controls rotation and the like. @@ -2294,6 +2310,29 @@ public class PhoneWindowManager implements WindowManagerPolicy { initKeyCombinationRules(); initSingleKeyGestureRules(); mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager); + + final String[] deviceKeyHandlerLibs = res.getStringArray( + com.android.internal.R.array.config_deviceKeyHandlerLibs); + final String[] deviceKeyHandlerClasses = res.getStringArray( + com.android.internal.R.array.config_deviceKeyHandlerClasses); + + for (int i = 0; + i < deviceKeyHandlerLibs.length && i < deviceKeyHandlerClasses.length; i++) { + try { + PathClassLoader loader = new PathClassLoader( + deviceKeyHandlerLibs[i], getClass().getClassLoader()); + Class<?> klass = loader.loadClass(deviceKeyHandlerClasses[i]); + Constructor<?> constructor = klass.getConstructor(Context.class); + mDeviceKeyHandlers.add((DeviceKeyHandler) constructor.newInstance(mContext)); + } catch (Exception e) { + Slog.w(TAG, "Could not instantiate device key handler " + + deviceKeyHandlerLibs[i] + " from class " + + deviceKeyHandlerClasses[i], e); + } + } + if (DEBUG_INPUT) { + Slog.d(TAG, "" + mDeviceKeyHandlers.size() + " device key handlers loaded"); + } } private void initKeyCombinationRules() { @@ -3316,6 +3355,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return key_consumed; } + // Specific device key handling + if (dispatchKeyToKeyHandlers(event)) { + return key_consumed; + } + // Reserve all the META modifier combos for system behavior if ((metaState & KeyEvent.META_META_ON) != 0) { return key_consumed; @@ -3408,6 +3452,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private boolean dispatchKeyToKeyHandlers(KeyEvent event) { + for (DeviceKeyHandler handler : mDeviceKeyHandlers) { + try { + if (DEBUG_INPUT) { + Log.d(TAG, "Dispatching key event " + event + " to handler " + handler); + } + event = handler.handleKeyEvent(event); + if (event == null) { + return true; + } + } catch (Exception e) { + Slog.w(TAG, "Could not dispatch event to device key handler", e); + } + } + return false; + } + // TODO(b/117479243): handle it in InputPolicy /** {@inheritDoc} */ @Override @@ -4150,6 +4211,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled) && event.getRepeatCount() == 0; + // Specific device key handling + if (dispatchKeyToKeyHandlers(event)) { + return 0; + } + // Handle special keys. switch (keyCode) { case KeyEvent.KEYCODE_BACK: { diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index a694e315ac29..5e6d06ed1009 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -119,6 +119,8 @@ public class Notifier { -1); private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); + private static final VibrationEffect CHARGING_VIBRATION_DOUBLE_CLICK_EFFECT = + VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK); private final Object mLock = new Object(); @@ -958,8 +960,8 @@ public class Notifier { final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(), Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0; if (vibrate) { - mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, - HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); + mVibrator.vibrate(mVibrator.hasAmplitudeControl() ? CHARGING_VIBRATION_EFFECT : + CHARGING_VIBRATION_DOUBLE_CLICK_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES); } // play sound diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java index 8431f1cc0b4c..a10e1da85dcc 100644 --- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java +++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java @@ -37,6 +37,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -44,6 +45,7 @@ import android.service.textservice.SpellCheckerService; import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; +import android.view.inputmethod.InputMethodSubtype; import android.view.textservice.SpellCheckerInfo; import android.view.textservice.SpellCheckerSubtype; import android.view.textservice.SuggestionsInfo; @@ -58,6 +60,7 @@ import com.android.internal.textservice.ISpellCheckerSessionListener; import com.android.internal.textservice.ITextServicesManager; import com.android.internal.textservice.ITextServicesSessionListener; import com.android.internal.util.DumpUtils; +import com.android.internal.view.IInputMethodManager; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -545,19 +548,44 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // subtypeHashCode == 0 means spell checker language settings is "auto" - if (systemLocale == null) { + Locale candidateLocale = null; + final IInputMethodManager imm = IInputMethodManager.Stub.asInterface( + ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); + if (imm != null) { + try { + final InputMethodSubtype currentInputMethodSubtype = + imm.getCurrentInputMethodSubtype(userId); + if (currentInputMethodSubtype != null) { + final String localeString = currentInputMethodSubtype.getLocale(); + if (!TextUtils.isEmpty(localeString)) { + // 1. Use keyboard locale if available in the spell checker + candidateLocale = + SubtypeLocaleUtils.constructLocaleFromString(localeString); + } + } + } catch (RemoteException e) { + Slog.e(TAG, "Exception getting input method subtype for " + userId, e); + } + } + + if (candidateLocale == null) { + // 2. Use System locale if available in the spell checker + candidateLocale = systemLocale; + } + + if (candidateLocale == null) { return null; } SpellCheckerSubtype firstLanguageMatchingSubtype = null; for (int i = 0; i < sci.getSubtypeCount(); ++i) { final SpellCheckerSubtype scs = sci.getSubtypeAt(i); final Locale scsLocale = scs.getLocaleObject(); - if (Objects.equals(scsLocale, systemLocale)) { + if (Objects.equals(scsLocale, candidateLocale)) { // Exact match wins. return scs; } if (firstLanguageMatchingSubtype == null && scsLocale != null - && TextUtils.equals(systemLocale.getLanguage(), scsLocale.getLanguage())) { + && TextUtils.equals(candidateLocale.getLanguage(), scsLocale.getLanguage())) { // Remember as a fall back candidate firstLanguageMatchingSubtype = scs; } diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java index 68f554cb2758..5604fc6c0f39 100644 --- a/services/core/java/com/android/server/webkit/SystemImpl.java +++ b/services/core/java/com/android/server/webkit/SystemImpl.java @@ -219,7 +219,7 @@ public class SystemImpl implements SystemInterface { @Override public boolean systemIsDebuggable() { - return Build.IS_DEBUGGABLE; + return Build.IS_DEBUGGABLE && Build.IS_ENG; } @Override diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9e3f541d3417..b32bc6ae109e 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -200,7 +200,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SERVICETRACKER; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP; import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION; @@ -314,7 +313,6 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; -import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.service.contentcapture.ActivityEvent; @@ -380,8 +378,6 @@ import com.android.server.wm.utils.InsetUtils; import dalvik.annotation.optimization.NeverCompile; -import com.google.android.collect.Sets; - import org.xmlpull.v1.XmlPullParserException; import java.io.File; @@ -397,10 +393,6 @@ import java.util.Objects; import java.util.function.Consumer; import java.util.function.Predicate; -import vendor.qti.hardware.servicetracker.V1_2.IServicetracker; -import vendor.qti.hardware.servicetracker.V1_2.ActivityDetails; -import vendor.qti.hardware.servicetracker.V1_2.ActivityStats; -import vendor.qti.hardware.servicetracker.V1_2.ActivityStates; /** * An entry in the history task, representing an activity. */ @@ -667,9 +659,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe public BoostFramework mPerf = null; public BoostFramework mPerf_iop = null; - private final boolean isLowRamDevice = - SystemProperties.getBoolean("ro.config.low_ram", false); - boolean mVoiceInteraction; private int mPendingRelaunchCount; @@ -2120,7 +2109,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe resultWho = _resultWho; requestCode = _reqCode; setState(INITIALIZING, "ActivityRecord ctor"); - callServiceTrackeronActivityStatechange(INITIALIZING, true); launchFailed = false; delayedResume = false; finishing = false; @@ -3580,19 +3568,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe } mDisplayContent.prepareAppTransition(TRANSIT_CLOSE); - // When finishing the activity preemptively take the snapshot before the app window - // is marked as hidden and any configuration changes take place - // Note that RecentsAnimation will handle task snapshot while switching apps with - // the best capture timing (e.g. IME window capture), - // No need additional task capture while task is controlled by RecentsAnimation. - if (!mTransitionController.isShellTransitionsEnabled() - && !task.isAnimatingByRecents()) { - final ArraySet<Task> tasks = Sets.newArraySet(task); - mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks); - mAtmService.mWindowManager.mTaskSnapshotController - .addSkipClosingAppSnapshotTasks(tasks); - } - // Tell window manager to prepare for this one to be removed. setVisibility(false); // Propagate the last IME visibility in the same task, so the IME can show @@ -3780,7 +3755,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe // destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); - callServiceTrackeronActivityStatechange(STOPPING, true); setState(STOPPING, "completeFinishing"); } else if (addToFinishingAndWaitForIdle()) { // We added this activity to the finishing list and something else is becoming @@ -3807,7 +3781,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe * destroying it until the next one starts. */ boolean destroyIfPossible(String reason) { - callServiceTrackeronActivityStatechange(FINISHING, true); setState(FINISHING, "destroyIfPossible"); // Make sure the record is cleaned out of other places. @@ -3859,7 +3832,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe @VisibleForTesting boolean addToFinishingAndWaitForIdle() { ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending finish: %s", this); - callServiceTrackeronActivityStatechange(FINISHING, true); setState(FINISHING, "addToFinishingAndWaitForIdle"); if (!mTaskSupervisor.mFinishingActivities.contains(this)) { mTaskSupervisor.mFinishingActivities.add(this); @@ -3930,14 +3902,12 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe // we are not removing it from the list. if (finishing && !skipDestroy) { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYING: %s (destroy requested)", this); - callServiceTrackeronActivityStatechange(DESTROYING, true); setState(DESTROYING, "destroyActivityLocked. finishing and not skipping destroy"); mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT); } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s " + "(destroy skipped)", this); - callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "destroyActivityLocked. not finishing or skipping destroy"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this); @@ -3950,7 +3920,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe removedFromHistory = true; } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (no app)", this); - callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); } } @@ -3987,7 +3956,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe removeTimeouts(); ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (removed from history)", this); - callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "removeFromHistory"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this); detachFromProcess(); @@ -4086,7 +4054,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe frozenBeforeDestroy = false; if (setState) { - callServiceTrackeronActivityStatechange(DESTROYED, true); setState(DESTROYED, "cleanUp"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this); detachFromProcess(); @@ -5799,8 +5766,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe mState = state; - callServiceTrackeronActivityStatechange(state, false); - if (getTaskFragment() != null) { getTaskFragment().onActivityStateChanged(this, state, reason); } @@ -5869,79 +5834,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe } } - void callServiceTrackeronActivityStatechange(State state, boolean early_notify) { - IServicetracker mServicetracker; - ActivityDetails aDetails = new ActivityDetails(); - ActivityStats aStats = new ActivityStats(); - int aState = ActivityStates.UNKNOWN; - - aDetails.launchedFromPid = this.launchedFromPid; - aDetails.launchedFromUid = this.launchedFromUid; - aDetails.packageName = this.packageName; - aDetails.processName = (this.processName!= null)? this.processName:"none"; - aDetails.intent = this.intent.getComponent().toString(); - aDetails.className = this.intent.getComponent().getClassName(); - aDetails.versioncode = this.info.applicationInfo.versionCode; - - aStats.createTime = this.createTime; - aStats.lastVisibleTime = this.lastVisibleTime; - aStats.launchCount = this.launchCount; - aStats.lastLaunchTime = this.lastLaunchTime; - - switch(state) { - case INITIALIZING : - aState = ActivityStates.INITIALIZING; - break; - case STARTED : - aState = ActivityStates.STARTED; - break; - case RESUMED : - aState = ActivityStates.RESUMED; - break; - case PAUSING : - aState = ActivityStates.PAUSING; - break; - case PAUSED : - aState = ActivityStates.PAUSED; - break; - case STOPPING : - aState = ActivityStates.STOPPING; - break; - case STOPPED: - aState = ActivityStates.STOPPED; - break; - case FINISHING : - aState = ActivityStates.FINISHING; - break; - case DESTROYING: - aState = ActivityStates.DESTROYING; - break; - case DESTROYED : - aState = ActivityStates.DESTROYED; - break; - case RESTARTING_PROCESS: - aState = ActivityStates.RESTARTING_PROCESS; - break; - } - if (!isLowRamDevice) { - if(DEBUG_SERVICETRACKER) { - Slog.v(TAG, "Calling mServicetracker.OnActivityStateChange with flag " - + early_notify + " state " + state); - } - try { - mServicetracker = mAtmService.mTaskSupervisor.getServicetrackerInstance(); - if (mServicetracker != null) - mServicetracker.OnActivityStateChange(aState, aDetails, aStats, early_notify); - else - Slog.e(TAG, "Unable to get servicetracker HAL instance"); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to send activity state change details to servicetracker HAL", e); - mAtmService.mTaskSupervisor.destroyServicetrackerInstance(); - } - } - - } - State getState() { return mState; } @@ -6227,7 +6119,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe } // An activity must be in the {@link PAUSING} state for the system to validate // the move to {@link PAUSED}. - callServiceTrackeronActivityStatechange(PAUSING, true); setState(PAUSING, "makeActiveIfNeeded"); EventLogTags.writeWmPauseActivity(mUserId, System.identityHashCode(this), shortComponentName, "userLeaving=false", "make-active"); @@ -6242,7 +6133,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Start visible activity, " + this); } - callServiceTrackeronActivityStatechange(STARTED, true); setState(STARTED, "makeActiveIfNeeded"); acquireActivityBoost(); try { @@ -6474,7 +6364,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe shortComponentName, pausingActivity != null ? pausingActivity.shortComponentName : "(none)"); if (isState(PAUSING)) { - callServiceTrackeronActivityStatechange(PAUSED, true); setState(PAUSED, "activityPausedLocked"); if (finishing) { ProtoLog.v(WM_DEBUG_STATES, @@ -6545,7 +6434,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe resumeKeyDispatchingLocked(); try { ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this); - callServiceTrackeronActivityStatechange(STOPPING, true); setState(STOPPING, "stopIfPossible"); getRootTask().onARStopTriggered(this); @@ -6565,7 +6453,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe // Just in case, assume it to be stopped. mAppStopped = true; ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this); - callServiceTrackeronActivityStatechange(STOPPED, true); setState(STOPPED, "stopIfPossible"); if (deferRelaunchUntilPaused) { destroyImmediately("stop-except"); @@ -6601,7 +6488,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe if (isStopping) { ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this); - callServiceTrackeronActivityStatechange(STOPPED, true); setState(STOPPED, "activityStopped"); } @@ -10047,7 +9933,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe mAtmService.getAppWarningsLocked().onResumeActivity(this); } else { removePauseTimeout(); - callServiceTrackeronActivityStatechange(PAUSED, true); setState(PAUSED, "relaunchActivityLocked"); } @@ -10078,7 +9963,6 @@ public final class ActivityRecord extends WindowToken implements WindowManagerSe } // The restarting state avoids removing this record when process is died. - callServiceTrackeronActivityStatechange(RESTARTING_PROCESS, true); setState(RESTARTING_PROCESS, "restartActivityProcess"); if (!mVisibleRequested || mHaveState) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java index 6671b360ed0b..33d1b44b9743 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerDebugConfig.java @@ -58,8 +58,6 @@ public class ActivityTaskManagerDebugConfig { static final boolean DEBUG_ACTIVITY_STARTS = DEBUG_ALL || false; public static final boolean DEBUG_CLEANUP = DEBUG_ALL || false; public static final boolean DEBUG_METRICS = DEBUG_ALL || false; - //Flag to enable Servicetracker logs in AOSP side - static final boolean DEBUG_SERVICETRACKER = false; static final String POSTFIX_APP = APPEND_CATEGORY_NAME ? "_App" : ""; static final String POSTFIX_CLEANUP = (APPEND_CATEGORY_NAME) ? "_Cleanup" : ""; diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index bcfcf21af0fe..43e6a4fd6a8c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -172,8 +172,6 @@ import java.util.function.Predicate; import java.util.Arrays; import android.os.AsyncTask; -import vendor.qti.hardware.servicetracker.V1_2.IServicetracker; - // TODO: This class has become a dumping ground. Let's // - Move things relating to the hierarchy to RootWindowContainer // - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler @@ -291,8 +289,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { private AppOpsManager mAppOpsManager; private VirtualDeviceManager mVirtualDeviceManager; - private IServicetracker mServicetracker; - /** Common synchronization logic used to save things to disks. */ PersisterQueue mPersisterQueue; LaunchParamsPersister mLaunchParamsPersister; @@ -489,28 +485,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mLaunchParamsPersister.onSystemReady(); } - public IServicetracker getServicetrackerInstance() { - if (mServicetracker == null) { - try { - mServicetracker = IServicetracker.getService(false); - } catch (java.util.NoSuchElementException e) { - // Service doesn't exist or cannot be opened logged below - } catch (RemoteException e) { - Slog.e(TAG, "Failed to get servicetracker interface", e); - return null; - } - if (mServicetracker == null) { - Slog.w(TAG, "servicetracker HIDL not available"); - return null; - } - } - return mServicetracker; - } - - public void destroyServicetrackerInstance() { - mServicetracker = null; - } - void onUserUnlocked(int userId) { // Only start persisting when the first user is unlocked. The method call is // idempotent so there is no side effect to call it again when the second user is diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java index c589feae56ca..51c93a6293b4 100644 --- a/services/core/java/com/android/server/wm/AlertWindowNotification.java +++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java @@ -24,6 +24,7 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.provider.Settings.ACTION_MANAGE_APP_OVERLAY_PERMISSION; +import android.annotation.UserIdInt; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -37,6 +38,7 @@ import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.os.UserHandle; import com.android.internal.R; import com.android.internal.util.ImageUtils; @@ -53,11 +55,14 @@ class AlertWindowNotification { private String mNotificationTag; private final NotificationManager mNotificationManager; private final String mPackageName; + private final @UserIdInt int mUserId; private boolean mPosted; - AlertWindowNotification(WindowManagerService service, String packageName) { + AlertWindowNotification(WindowManagerService service, String packageName, + @UserIdInt int userId) { mService = service; mPackageName = packageName; + mUserId = userId; mNotificationManager = (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE); mNotificationTag = CHANNEL_PREFIX + mPackageName; @@ -100,7 +105,7 @@ class AlertWindowNotification { final Context context = mService.mContext; final PackageManager pm = context.getPackageManager(); - final ApplicationInfo aInfo = getApplicationInfo(pm, mPackageName); + final ApplicationInfo aInfo = getApplicationInfoAsUser(pm, mPackageName, mUserId); final String appName = (aInfo != null) ? pm.getApplicationLabel(aInfo).toString() : mPackageName; @@ -138,6 +143,7 @@ class AlertWindowNotification { final Intent intent = new Intent(ACTION_MANAGE_APP_OVERLAY_PERMISSION, Uri.fromParts("package", packageName, null)); intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); + intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.of(mUserId)); // Calls into activity manager... return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE); @@ -168,9 +174,10 @@ class AlertWindowNotification { } - private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) { + private ApplicationInfo getApplicationInfoAsUser(PackageManager pm, String packageName, + @UserIdInt int userId) { try { - return pm.getApplicationInfo(packageName, 0); + return pm.getApplicationInfoAsUser(packageName, 0, userId); } catch (PackageManager.NameNotFoundException e) { return null; } diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java index 43baebc7255a..e646f14a3e13 100644 --- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java +++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java @@ -114,9 +114,15 @@ public class RemoteDisplayChangeController { // timed-out, so run all continue callbacks and clear the list synchronized (mService.mGlobalLock) { for (int i = 0; i < mCallbacks.size(); ++i) { - mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */); + final ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i); + if (i == mCallbacks.size() - 1) { + // Clear all callbacks before calling the last one, so that if the callback + // itself calls {@link #isWaitingForRemoteDisplayChange()}, it will get + // {@code false}. After all, there is nothing pending after this one. + mCallbacks.clear(); + } + callback.onContinueRemoteDisplayChange(null /* transaction */); } - mCallbacks.clear(); } } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 7b10c6372b0e..0a3e79ed5e00 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -750,7 +750,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { if (mAlertWindowSurfaces.isEmpty()) { cancelAlertWindowNotification(); } else if (mAlertWindowNotification == null){ - mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName); + mAlertWindowNotification = new AlertWindowNotification(mService, mPackageName, + UserHandle.getUserId(mUid)); if (mShowingAlertWindowNotificationAllowed) { mAlertWindowNotification.post(); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 5edb11c0f6e5..083a651af385 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -877,7 +877,7 @@ public final class SystemServer implements Dumpable { initZygoteChildHeapProfiling(); // Debug builds - spawn a thread to monitor for fd leaks. - if (Build.IS_DEBUGGABLE) { + if (Build.IS_ENG) { spawnFdLeakCheckThread(); } diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java index 47ae97fc5d27..24386f865fc1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java @@ -678,7 +678,7 @@ public class AppStateTrackerTest { new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, new boolean[] {false, false, false, false, false}); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_1}, new int[] {}, + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_1}, new int[] {}, new int[] {UID_2}); areJobsRestricted(instance, @@ -728,8 +728,8 @@ public class AppStateTrackerTest { @Test public void testPowerSaveUserExemptionList() throws Exception { final AppStateTrackerTestable instance = newInstance(); - instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_1, UID_2}, - new int[] {}); + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {}, + new int[] {UID_1, UID_2}, new int[] {}); assertTrue(instance.isUidPowerSaveUserExempt(UID_1)); assertTrue(instance.isUidPowerSaveUserExempt(UID_2)); assertFalse(instance.isUidPowerSaveUserExempt(UID_3)); @@ -1188,8 +1188,8 @@ public class AppStateTrackerTest { // ------------------------------------------------------------------------- // Tests with system/user/temp exemption list. - instance.setPowerSaveExemptionListAppIds(new int[] {UID_1, UID_2}, new int[] {}, - new int[] {}); + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_1, UID_2}, + new int[] {}, new int[] {}); waitUntilMainHandlerDrain(); verify(l, times(1)).updateAllJobs(); @@ -1205,7 +1205,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, new int[] {}); + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, + new int[] {}); waitUntilMainHandlerDrain(); verify(l, times(1)).updateAllJobs(); @@ -1222,7 +1223,7 @@ public class AppStateTrackerTest { reset(l); // Update temp exemption list. - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, new int[] {UID_1, UID_3}); waitUntilMainHandlerDrain(); @@ -1239,7 +1240,7 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, new int[] {UID_3}); waitUntilMainHandlerDrain(); @@ -1274,8 +1275,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_1, UID_2}, new int[] {}, - new int[] {}); + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_1, UID_2}, + new int[] {}, new int[] {}); waitUntilMainHandlerDrain(); // Called once for updating all exemption list and once for updating temp exemption list @@ -1292,7 +1293,8 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, new int[] {}); + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, + new int[] {}); waitUntilMainHandlerDrain(); verify(l, times(1)).updateAllJobs(); @@ -1309,7 +1311,7 @@ public class AppStateTrackerTest { reset(l); // Update temp exemption list. - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, new int[] {UID_1, UID_3}); waitUntilMainHandlerDrain(); @@ -1326,7 +1328,7 @@ public class AppStateTrackerTest { verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, + instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_2}, new int[] {}, new int[] {UID_3}); waitUntilMainHandlerDrain(); diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 06fca116a185..cf31e719d6b1 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -10306,7 +10306,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL, false); sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, ""); sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, ""); - sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true); + sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, false); sDefaults.putBoolean(KEY_SHOW_5G_SLICE_ICON_BOOL, true); sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000); sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 99b432ac6f1d..f5507a0dc764 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -15310,8 +15310,6 @@ public class TelephonyManager { if (version != -1) { return new Pair<Integer, Integer>(version / 100, version % 100); } - } else { - throw new IllegalStateException("telephony service is null."); } } catch (RemoteException e) { Log.e(TAG, "getHalVersion() RemoteException", e); |