diff options
6 files changed, 211 insertions, 4 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fb59ae9a26e8..d756ca9769e2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5183,6 +5183,15 @@ public final class Settings { public static final String MULTI_AUDIO_FOCUS_ENABLED = "multi_audio_focus_enabled"; /** + * Whether user can swap the order of the Alert Slider. + * * Whether user can invert the order of the Alert Slider. + * 0: Default + * 1: Inverted + * @hide + */ + public static final String ALERT_SLIDER_ORDER = "alert_slider_order"; + + /** * 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 diff --git a/core/res/res/values/ice_config.xml b/core/res/res/values/ice_config.xml index a4794dbcc5e5..4653c7410805 100644 --- a/core/res/res/values/ice_config.xml +++ b/core/res/res/values/ice_config.xml @@ -44,7 +44,14 @@ <!-- 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 --> + <!-- 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> + + <!-- Path to proc nodes for alert slider --> + <string name="alert_slider_state_path" translatable="false"></string> + <string name="alert_slider_uevent_match_path" translatable="false"></string> + </resources> diff --git a/core/res/res/values/ice_symbols.xml b/core/res/res/values/ice_symbols.xml index 1471cba86f36..b1978e66f339 100644 --- a/core/res/res/values/ice_symbols.xml +++ b/core/res/res/values/ice_symbols.xml @@ -33,4 +33,9 @@ <!-- 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="string" name="alert_slider_state_path" /> + <java-symbol type="string" name="alert_slider_uevent_match_path" /> + </resources> diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c0b58998ddf1..5e18ecd93f71 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -146,6 +146,7 @@ import android.view.KeyEvent; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; @@ -783,6 +784,9 @@ public class AudioService extends IAudioService.Stub private @AttributeSystemUsage int[] mSupportedSystemUsages = new int[]{AudioAttributes.USAGE_CALL_ASSISTANT}; + // Alert Slider + private boolean mHasAlertSlider = false; + // Defines the format for the connection "address" for ALSA devices public static String makeAlsaAddressString(int card, int device) { return "card=" + card + ";device=" + device + ";"; @@ -882,6 +886,10 @@ public class AudioService extends IAudioService.Stub mUseVolumeGroupAliases = mContext.getResources().getBoolean( com.android.internal.R.bool.config_handleVolumeAliasesUsingVolumeGroups); + mHasAlertSlider = mContext.getResources().getBoolean(R.bool.config_hasAlertSlider) + && !TextUtils.isEmpty(mContext.getResources().getString(R.string.alert_slider_state_path)) + && !TextUtils.isEmpty(mContext.getResources().getString(R.string.alert_slider_uevent_match_path)); + // Initialize volume // Priority 1 - Android Property // Priority 2 - Audio Policy Service @@ -2738,6 +2746,27 @@ public class AudioService extends IAudioService.Stub } } + if (mHasAlertSlider) { + int volumeType = mStreamVolumeAlias[streamType]; + VolumeStreamState volumeState = mStreamStates[volumeType]; + int state = getDeviceForStream(volumeType); + int index = volumeState.getIndex(state); + int ringerMode = getRingerModeInternal(); + if ((volumeType == AudioSystem.STREAM_RING) + && (direction == AudioManager.ADJUST_LOWER) + && (index == 0)) { + direction = AudioManager.ADJUST_SAME; + } + if ((ringerMode == AudioManager.RINGER_MODE_SILENT) + && (direction == AudioManager.ADJUST_RAISE + && volumeType != AudioSystem.STREAM_MUSIC + && volumeType != AudioSystem.STREAM_ALARM + && volumeType != AudioSystem.STREAM_VOICE_CALL + && !isInCommunication())) { + direction = AudioManager.ADJUST_SAME; + } + } + final boolean isMute = isMuteAdjust(direction); ensureValidStreamType(streamType); diff --git a/services/core/java/com/android/server/policy/AlertSliderObserver.java b/services/core/java/com/android/server/policy/AlertSliderObserver.java new file mode 100644 index 000000000000..d64d744403e1 --- /dev/null +++ b/services/core/java/com/android/server/policy/AlertSliderObserver.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2021 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.server.policy; + +import android.app.NotificationManager; +import android.content.Context; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.UEventObserver; +import android.os.UserHandle; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; +import android.util.Slog; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +public class AlertSliderObserver extends UEventObserver { + private static final String TAG = AlertSliderObserver.class.getSimpleName(); + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private int mState; + + private final Context mContext; + private final AudioManager mAudioManager; + private final WakeLock mWakeLock; + + public AlertSliderObserver(Context context) { + mContext = context; + mAudioManager = context.getSystemService(AudioManager.class); + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AlertSliderObserver"); + init(); + } + + protected void startObserving(int pathId) { + String matchPath = mContext.getResources().getString(pathId); + if (!TextUtils.isEmpty(matchPath)) { + super.startObserving(matchPath); + } + } + + @Override + public void onUEvent(UEventObserver.UEvent event) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Slog.v(TAG, "Switch UEVENT: " + event.toString()); + } + + try { + int state = Integer.parseInt(event.get("SWITCH_STATE")); + if (state != mState) { + mState = state; + update(); + } + } catch (NumberFormatException e) { + Slog.e(TAG, "Could not parse switch state from event " + event); + } + } + + private void init() { + try { + final String path = mContext.getResources().getString( + com.android.internal.R.string.alert_slider_state_path); + FileReader file = new FileReader(path); + BufferedReader br = new BufferedReader(file); + String value = br.readLine(); + file.close(); + br.close(); + mState = Integer.valueOf(value); + update(); + } catch (IOException e) { + Slog.w(TAG, "This device does not have an Alert Slider"); + stopObserving(); + } + } + + protected void update() { + // Acquire wakelock when slider state changes. + mWakeLock.acquire(); + mHandler.sendEmptyMessageDelayed(mState, 100); + } + + private Handler mHandler = new Handler(Looper.myLooper(), null, true) { + @Override + public void handleMessage(Message msg) { + final boolean inverted = isOrderInverted(); + switch (mState) { + case 1: + mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_SILENT); + break; + case 2: + mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_VIBRATE); + break; + case 3: + mAudioManager.setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL); + break; + } + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } + }; + + // Check if ordered has been set to inverted. + private boolean isOrderInverted() { + return Settings.System.getIntForUser( + mContext.getContentResolver(), Settings.System.ALERT_SLIDER_ORDER, 0, + UserHandle.USER_CURRENT) != 0; + } +} diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fdd2b14cbd22..61097decdefb 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -134,6 +134,7 @@ import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.IAudioService; import android.media.session.MediaSessionLegacyHelper; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.DeviceIdleManager; @@ -164,6 +165,7 @@ import android.service.dreams.IDreamManager; import android.service.vr.IPersistentVrStateCallbacks; import android.speech.RecognizerIntent; import android.telecom.TelecomManager; +import android.text.TextUtils; import android.util.Log; import android.util.MutableBoolean; import android.util.PrintWriterPrinter; @@ -387,6 +389,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { AppOpsManager mAppOpsManager; PackageManager mPackageManager; SideFpsEventHandler mSideFpsEventHandler; + AlertSliderObserver mAlertSliderObserver; private boolean mHasFeatureAuto; private boolean mHasFeatureWatch; private boolean mHasFeatureLeanback; @@ -628,6 +631,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_LAUNCH_ASSIST = 23; private static final int MSG_RINGER_TOGGLE_CHORD = 24; + private boolean mHasAlertSlider = false; + private class PolicyHandler extends Handler { @Override public void handleMessage(Message msg) { @@ -722,6 +727,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { }; class SettingsObserver extends ContentObserver { + private final Uri SWAP_ALERT_SLIDER_ORDER_URI = + Settings.System.getUriFor(Settings.System.ALERT_SLIDER_ORDER); + SettingsObserver(Handler handler) { super(handler); } @@ -768,12 +776,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.ALERT_SLIDER_ORDER), false, this, + UserHandle.USER_ALL); updateSettings(); } - @Override public void onChange(boolean selfChange) { - updateSettings(); - updateRotation(false); + @Override + public void onChange(boolean selfChange, Uri uri) { + if (SWAP_ALERT_SLIDER_ORDER_URI.equals(uri) + && mSystemReady && mAlertSliderObserver != null) { + mAlertSliderObserver.update(); + } else { + updateSettings(); + updateRotation(false); + } } } @@ -1659,6 +1676,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWakeOnBackKeyPress = res.getBoolean(com.android.internal.R.bool.config_wakeOnBackKeyPress); + // Init alert slider + mHasAlertSlider = mContext.getResources().getBoolean(R.bool.config_hasAlertSlider) + && !TextUtils.isEmpty(mContext.getResources().getString(R.string.alert_slider_state_path)) + && !TextUtils.isEmpty(mContext.getResources().getString(R.string.alert_slider_uevent_match_path)); + // Init display burn-in protection boolean burnInProtectionEnabled = context.getResources().getBoolean( com.android.internal.R.bool.config_enableBurnInProtection); @@ -4790,6 +4812,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener); } + if (mHasAlertSlider) { + mAlertSliderObserver = new AlertSliderObserver(mContext); + mAlertSliderObserver.startObserving(com.android.internal.R.string.alert_slider_uevent_match_path); + } + readCameraLensCoverState(); updateUiMode(); mDefaultDisplayRotation.updateOrientationListener(); |