blob: dc6dbf0a89640870d8acc8986378817cbc304780 [file]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server.telecom;
import android.content.ContentResolver;
import android.content.Context;
import android.media.AudioManager;
import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.Vibrator;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.telecom.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.flags.Flags;
/**
* Accesses the Global System settings for more control during testing.
*/
@VisibleForTesting
public class SystemSettingsUtil {
/**
* TODO(b/441480678): Cleanup to link to the proper API in system settings.
*/
public static final String RING_VIBRATION_INTENSITY = "ring_vibration_intensity";
/**
* The lowest vibration intensity, which is 0 meaning that the vibration is disabled.
*/
public static final int VIBRATION_INTENSITY_OFF = 0;
/**
* Abstracts away the static {@link Settings.System} calls so they can be mocked in tests.
*/
@VisibleForTesting
public interface SystemSettingsReader {
int getInt(ContentResolver cr, String name, int def);
int getIntForUser(Context context, String name, int def, int userHandle);
}
private static class DefaultSystemSettingsReader implements SystemSettingsReader {
@Override
public int getInt(ContentResolver cr, String name, int def) {
return Settings.System.getInt(cr, name, def);
}
@Override
public int getIntForUser(Context context, String name, int def, int userHandle) {
return Settings.System.getInt(
context.createContextAsUser(UserHandle.of(userHandle), 0).getContentResolver(),
name, def);
}
}
private final SystemSettingsReader mSystemSettingsReader;
public SystemSettingsUtil() {
this(new DefaultSystemSettingsReader());
}
@VisibleForTesting
public SystemSettingsUtil(SystemSettingsReader systemSettingsReader) {
mSystemSettingsReader = systemSettingsReader;
}
/** Flag for whether or not to support audio coupled haptics in ramping ringer. */
private static final String RAMPING_RINGER_AUDIO_COUPLED_VIBRATION_ENABLED =
"ramping_ringer_audio_coupled_vibration_enabled";
/**
* Determines if the primary "vibration" toggle is on in the system settings (see Settings -->
* Sound and Vibration --> Vibration and Haptics --> Use Vibration and Haptics).
* @param context the context to use for checking the settings.
* @return {@code true} if the primary haptic toggle is on, {@code false} otherwise.
*/
private boolean isVibrationEnabled(Context context) {
if (!Flags.vibrationAccountsForMainSetting()) {
return true;
}
// Note, there is no constant for the on/off. 0 is used elsewhere in the platform when this
// key is referenced.
return mSystemSettingsReader.getInt(context.getContentResolver(),
Settings.System.VIBRATE_ON, 1) != 0;
}
public boolean isRingVibrationEnabled(Context context) {
// Ramping ringer should only be applied when ring vibration is ON, otherwise the
// ringtone sound should not be delayed as there will be no ring vibration.
// Note: VIBRATE_WHEN_RINGING is deprecated but is currently the only system API that
// the Haptics Framework team provides. For mainlining Telecom, using
// VIBRATE_WHEN_RINGING is our only option currently until the request for a new system
// API (b/441480678) has been met.
int defaultIntensity = 2; // VIBRATION_INTENSITY_MEDIUM
// There have been reported issues where the user has enabled vibrations but when we query
// the deprecated Settings.System.VIBRATE_WHEN_RINGING it looks like vibration is disabled.
// Settings is responsible for keeping the two in sync, so it looks like there are cases
// where they get out of sync and vibration fails to play.
int currentVibrationIntensity = mSystemSettingsReader.getInt
(context.getContentResolver(), RING_VIBRATION_INTENSITY, defaultIntensity);
boolean isVibrationEnabledDueToIntensity =
currentVibrationIntensity != VIBRATION_INTENSITY_OFF;
// We'll also check to see if the old setting said we should vibrate or not.
boolean isVibrationEnabledDueToDeprecatedSetting = mSystemSettingsReader.getInt
(context.getContentResolver(),
Settings.System.VIBRATE_WHEN_RINGING,
/*context.getSystemService(Vibrator.class)
.getDefaultVibrationIntensity(VibrationAttributes.USAGE_RINGTONE)*/
defaultIntensity) != 0;
// If they're out of sync, log a warning so we can diagnose in a bug report easier.
if (isVibrationEnabledDueToDeprecatedSetting != isVibrationEnabledDueToIntensity) {
Log.w(this,
"isRingVibrationEnabled: currentVibrationIntensity=%d, "
+ "isVibrationEnabledDueToIntensity=%b, "
+ "isVibrationEnabledDueToDeprecatedSetting=%b",
currentVibrationIntensity, isVibrationEnabledDueToIntensity,
isVibrationEnabledDueToDeprecatedSetting);
}
return isVibrationEnabledDueToIntensity && isVibrationEnabled(context);
}
public boolean isRampingRingerEnabled(Context context) {
return context.getSystemService(AudioManager.class).isRampingRingerEnabled();
}
public boolean isAudioCoupledVibrationForRampingRingerEnabled() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY,
RAMPING_RINGER_AUDIO_COUPLED_VIBRATION_ENABLED, false);
}
public boolean isHapticPlaybackSupported(Context context) {
return context.getSystemService(AudioManager.class).isHapticPlaybackSupported();
}
}