Dialer: Fix settings
* RingtonePreference doesn't exist in androidx world - we have to
make our own
* We don't need to remove the dividers anymore - androidx doesn't have
them in the first place
* AppCompatPreferenceActivity is deprecated as well, make it
an AppCompatActivity and start using fragments
Change-Id: I54d22868deb8950618b69652ae3810b8e0bcdb80
diff --git a/java/com/android/dialer/app/res/layout/activity_settings.xml b/java/com/android/dialer/app/res/layout/activity_settings.xml
new file mode 100644
index 0000000..e53ce21
--- /dev/null
+++ b/java/com/android/dialer/app/res/layout/activity_settings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/content_frame" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/java/com/android/dialer/app/settings/AppCompatPreferenceActivity.java b/java/com/android/dialer/app/settings/AppCompatPreferenceActivity.java
deleted file mode 100644
index ee8c424..0000000
--- a/java/com/android/dialer/app/settings/AppCompatPreferenceActivity.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- * 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.dialer.app.settings;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.appcompat.app.AppCompatDelegate;
-
-/**
- * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
- * to be used with AppCompat.
- */
-public class AppCompatPreferenceActivity extends PreferenceActivity {
-
- private AppCompatDelegate delegate;
-
- private boolean isSafeToCommitTransactions;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- getDelegate().installViewFactory();
- getDelegate().onCreate(savedInstanceState);
- super.onCreate(savedInstanceState);
- isSafeToCommitTransactions = true;
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- getDelegate().onPostCreate(savedInstanceState);
- }
-
- @Override
- public MenuInflater getMenuInflater() {
- return getDelegate().getMenuInflater();
- }
-
- @Override
- public void setContentView(int layoutResID) {
- getDelegate().setContentView(layoutResID);
- }
-
- @Override
- public void setContentView(View view) {
- getDelegate().setContentView(view);
- }
-
- @Override
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().setContentView(view, params);
- }
-
- @Override
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().addContentView(view, params);
- }
-
- @Override
- protected void onPostResume() {
- super.onPostResume();
- getDelegate().onPostResume();
- }
-
- @Override
- protected void onTitleChanged(CharSequence title, int color) {
- super.onTitleChanged(title, color);
- getDelegate().setTitle(title);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- getDelegate().onConfigurationChanged(newConfig);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- getDelegate().onStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- getDelegate().onDestroy();
- }
-
- @Override
- public void invalidateOptionsMenu() {
- getDelegate().invalidateOptionsMenu();
- }
-
- private AppCompatDelegate getDelegate() {
- if (delegate == null) {
- delegate = AppCompatDelegate.create(this, null);
- }
- return delegate;
- }
-
- @Override
- protected void onStart() {
- super.onStart();
- isSafeToCommitTransactions = true;
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- isSafeToCommitTransactions = true;
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- isSafeToCommitTransactions = false;
- }
-
- /**
- * Returns true if it is safe to commit {@link FragmentTransaction}s at this time, based on
- * whether {@link Activity#onSaveInstanceState} has been called or not.
- *
- * <p>Make sure that the current activity calls into {@link super.onSaveInstanceState(Bundle
- * outState)} (if that method is overridden), so the flag is properly set.
- */
- public boolean isSafeToCommitTransactions() {
- return isSafeToCommitTransactions;
- }
-}
diff --git a/java/com/android/dialer/app/settings/DefaultRingtonePreference.java b/java/com/android/dialer/app/settings/DefaultRingtonePreference.java
index 50989ce..cbabb74 100644
--- a/java/com/android/dialer/app/settings/DefaultRingtonePreference.java
+++ b/java/com/android/dialer/app/settings/DefaultRingtonePreference.java
@@ -21,32 +21,44 @@
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
-import android.preference.RingtonePreference;
import android.provider.Settings;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.Toast;
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+
import com.android.dialer.R;
/** RingtonePreference which doesn't show default ringtone setting. */
-public class DefaultRingtonePreference extends RingtonePreference {
+public class DefaultRingtonePreference extends Preference {
+
+ private final Intent mRingtonePickerIntent;
public DefaultRingtonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ mRingtonePickerIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, getRingtoneType());
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI,
+ Settings.System.DEFAULT_NOTIFICATION_URI);
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, getTitle());
}
- @Override
- protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
- super.onPrepareRingtonePickerIntent(ringtonePickerIntent);
-
- /*
- * Since this preference is for choosing the default ringtone, it
- * doesn't make sense to show a 'Default' item.
- */
- ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
+ public Intent getRingtonePickerIntent() {
+ mRingtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
+ onRestoreRingtone());
+ return mRingtonePickerIntent;
}
- @Override
protected void onSaveRingtone(Uri ringtoneUri) {
if (!Settings.System.canWrite(getContext())) {
Toast.makeText(
@@ -59,8 +71,11 @@
RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);
}
- @Override
protected Uri onRestoreRingtone() {
return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());
}
+
+ private int getRingtoneType() {
+ return RingtoneManager.TYPE_RINGTONE;
+ }
}
diff --git a/java/com/android/dialer/app/settings/DialerPreferenceFragment.java b/java/com/android/dialer/app/settings/DialerPreferenceFragment.java
deleted file mode 100644
index d2af4de..0000000
--- a/java/com/android/dialer/app/settings/DialerPreferenceFragment.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * SPDX-FileCopyrightText: The LineageOS Project
- * SPDX-License-Identifier: Apache-2.0
- */
-package com.android.dialer.app.settings;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.ListView;
-
-import androidx.annotation.Nullable;
-import androidx.preference.PreferenceFragmentCompat;
-
-public class DialerPreferenceFragment extends PreferenceFragmentCompat {
-
- @Override
- public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
-
- }
-
- @Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- ListView lv = (ListView) view.findViewById(android.R.id.list);
- if (lv != null) {
- lv.setDivider(null);
- }
- }
-}
diff --git a/java/com/android/dialer/app/settings/DialerSettingsActivity.java b/java/com/android/dialer/app/settings/DialerSettingsActivity.java
index 5e08ed9..ec7d85e 100644
--- a/java/com/android/dialer/app/settings/DialerSettingsActivity.java
+++ b/java/com/android/dialer/app/settings/DialerSettingsActivity.java
@@ -16,6 +16,7 @@
*/
package com.android.dialer.app.settings;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -28,30 +29,29 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
-import android.view.MenuItem;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
-import com.android.dialer.app.R;
+import com.android.dialer.R;
import com.android.dialer.common.LogUtil;
import com.android.dialer.compat.telephony.TelephonyManagerCompat;
import com.android.dialer.lookup.LookupSettingsFragment;
-import com.android.dialer.proguard.UsedByReflection;
import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.voicemail.settings.VoicemailSettingsFragment;
import com.android.voicemail.VoicemailClient;
-import java.util.List;
-
/** Activity for dialer settings. */
-@SuppressWarnings("FragmentInjection") // Activity not exported
-@UsedByReflection(value = "AndroidManifest-app.xml")
-public class DialerSettingsActivity extends AppCompatPreferenceActivity {
+public class DialerSettingsActivity extends AppCompatActivity implements
+ PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
protected SharedPreferences preferences;
- private List<Header> headers;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -59,225 +59,241 @@
super.onCreate(savedInstanceState);
preferences = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext());
+ setContentView(R.layout.activity_settings);
+
Intent intent = getIntent();
Uri data = intent.getData();
+
+ String initialFragment = null;
if (data != null) {
String headerToOpen = data.getSchemeSpecificPart();
- if (headerToOpen != null && headers != null) {
- for (Header header : headers) {
- if (headerToOpen.equals(header.fragment)) {
- LogUtil.i("DialerSettingsActivity.onCreate", "switching to header: " + headerToOpen);
- switchToHeader(header);
- break;
- }
- }
+ if (headerToOpen != null) {
+ initialFragment = headerToOpen;
}
}
- }
- @Override
- protected void onResume() {
- super.onResume();
- }
-
- @Override
- public void onBuildHeaders(List<Header> target) {
- // Keep a reference to the list of headers (since PreferenceActivity.getHeaders() is @Hide)
- headers = target;
-
- if (showDisplayOptions()) {
- Header displayOptionsHeader = new Header();
- displayOptionsHeader.titleRes = R.string.display_options_title;
- displayOptionsHeader.fragment = DisplayOptionsSettingsFragment.class.getName();
- target.add(displayOptionsHeader);
- }
-
- Header soundSettingsHeader = new Header();
- soundSettingsHeader.titleRes = R.string.sounds_and_vibration_title;
- soundSettingsHeader.fragment = SoundSettingsFragment.class.getName();
- soundSettingsHeader.id = R.id.settings_header_sounds_and_vibration;
- target.add(soundSettingsHeader);
-
- Header quickResponseSettingsHeader = new Header();
- Intent quickResponseSettingsIntent =
- new Intent(TelecomManager.ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS);
- quickResponseSettingsHeader.titleRes = R.string.respond_via_sms_setting_title;
- quickResponseSettingsHeader.intent = quickResponseSettingsIntent;
- target.add(quickResponseSettingsHeader);
-
- final Header lookupSettingsHeader = new Header();
- lookupSettingsHeader.titleRes = R.string.lookup_settings_label;
- lookupSettingsHeader.fragment = LookupSettingsFragment.class.getName();
- target.add(lookupSettingsHeader);
-
- TelephonyManager telephonyManager =
- (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
-
- // "Call Settings" (full settings) is shown if the current user is primary user and there
- // is only one SIM. Otherwise, "Calling accounts" is shown.
- boolean isPrimaryUser = isPrimaryUser();
- if (isPrimaryUser && TelephonyManagerCompat.getPhoneCount(telephonyManager) <= 1) {
- Header callSettingsHeader = new Header();
- Intent callSettingsIntent = new Intent(TelecomManager.ACTION_SHOW_CALL_SETTINGS);
- callSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
- callSettingsHeader.titleRes = R.string.call_settings_label;
- callSettingsHeader.intent = callSettingsIntent;
- target.add(callSettingsHeader);
- } else {
- Header phoneAccountSettingsHeader = new Header();
- Intent phoneAccountSettingsIntent = new Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS);
- phoneAccountSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-
- phoneAccountSettingsHeader.titleRes = R.string.phone_account_settings_label;
- phoneAccountSettingsHeader.intent = phoneAccountSettingsIntent;
- target.add(phoneAccountSettingsHeader);
- }
- if (BlockedNumberContract.canCurrentUserBlockNumbers(this)) {
- Header blockedCallsHeader = new Header();
- blockedCallsHeader.titleRes = R.string.manage_blocked_numbers_label;
- blockedCallsHeader.intent = getApplicationContext().getSystemService(TelecomManager.class)
- .createManageBlockedNumbersIntent();
- target.add(blockedCallsHeader);
- }
-
- addVoicemailSettings(target, isPrimaryUser);
-
- if (isPrimaryUser
- && (TelephonyManagerCompat.isTtyModeSupported(telephonyManager)
- || TelephonyManagerCompat.isHearingAidCompatibilitySupported(telephonyManager))) {
- Header accessibilitySettingsHeader = new Header();
- Intent accessibilitySettingsIntent =
- new Intent(TelecomManager.ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS);
- accessibilitySettingsHeader.titleRes = R.string.accessibility_settings_title;
- accessibilitySettingsHeader.intent = accessibilitySettingsIntent;
- target.add(accessibilitySettingsHeader);
- }
- }
-
- private void addVoicemailSettings(List<Header> target, boolean isPrimaryUser) {
- if (!isPrimaryUser) {
- LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "user not primary user");
- return;
- }
-
- if (!PermissionsUtil.hasReadPhoneStatePermissions(this)) {
- LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "Missing READ_PHONE_STATE");
- return;
- }
-
- LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "adding voicemail settings");
- Header voicemailSettings = new Header();
- voicemailSettings.titleRes = R.string.voicemail_settings_label;
- PhoneAccountHandle soleAccount = getSoleSimAccount();
- if (soleAccount == null) {
- LogUtil.i(
- "DialerSettingsActivity.addVoicemailSettings", "showing multi-SIM voicemail settings");
- voicemailSettings.fragment = PhoneAccountSelectionFragment.class.getName();
- Bundle bundle = new Bundle();
- bundle.putString(
- PhoneAccountSelectionFragment.PARAM_TARGET_FRAGMENT,
- VoicemailSettingsFragment.class.getName());
- bundle.putString(
- PhoneAccountSelectionFragment.PARAM_PHONE_ACCOUNT_HANDLE_KEY,
- VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE);
- bundle.putBundle(PhoneAccountSelectionFragment.PARAM_ARGUMENTS, new Bundle());
- bundle.putInt(
- PhoneAccountSelectionFragment.PARAM_TARGET_TITLE_RES, R.string.voicemail_settings_label);
- voicemailSettings.fragmentArguments = bundle;
- target.add(voicemailSettings);
- } else {
- LogUtil.i(
- "DialerSettingsActivity.addVoicemailSettings", "showing single-SIM voicemail settings");
- voicemailSettings.fragment = VoicemailSettingsFragment.class.getName();
- Bundle bundle = new Bundle();
- bundle.putParcelable(VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE, soleAccount);
- voicemailSettings.fragmentArguments = bundle;
- target.add(voicemailSettings);
- }
- }
-
- /**
- * @return the only SIM phone account, or {@code null} if there are none or more than one. Note:
- * having a empty SIM slot still count as a PhoneAccountHandle that is "invalid", and
- * voicemail settings should still be available for it.
- */
- @Nullable
- private PhoneAccountHandle getSoleSimAccount() {
- TelecomManager telecomManager = getSystemService(TelecomManager.class);
- PhoneAccountHandle result = null;
- for (PhoneAccountHandle phoneAccountHandle : telecomManager.getCallCapablePhoneAccounts()) {
- PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle);
- if (phoneAccount == null) {
- continue;
+ // If savedInstanceState is non-null, then the activity is being
+ // recreated and super.onCreate() has already recreated the fragment.
+ if (savedInstanceState == null) {
+ if (initialFragment == null) {
+ initialFragment = PrefsFragment.class.getName();
}
- if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
- LogUtil.i(
- "DialerSettingsActivity.getSoleSimAccount", phoneAccountHandle + " is a SIM account");
- if (result != null) {
- return null;
- }
- result = phoneAccountHandle;
+ Fragment fragment;
+ try {
+ fragment = getSupportFragmentManager()
+ .getFragmentFactory()
+ .instantiate(getClassLoader(), initialFragment);
+ } catch (Exception ignored) {
+ fragment = new PrefsFragment();
}
+
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.content_frame, fragment)
+ .commit();
}
- return result;
- }
- /**
- * Returns {@code true} or {@code false} based on whether the display options setting should be
- * shown. For languages such as Chinese, Japanese, or Korean, display options aren't useful since
- * contacts are sorted and displayed family name first by default.
- *
- * @return {@code true} if the display options should be shown, {@code false} otherwise.
- */
- private boolean showDisplayOptions() {
- return getResources().getBoolean(R.bool.config_display_order_user_changeable)
- && getResources().getBoolean(R.bool.config_sort_order_user_changeable);
- }
-
- @Override
- public void onHeaderClick(Header header, int position) {
- if (header.id == R.id.settings_header_sounds_and_vibration) {
- // If we don't have the permission to write to system settings, go to system sound
- // settings instead. Otherwise, perform the super implementation (which launches our
- // own preference fragment.
- if (!Settings.System.canWrite(this)) {
- Toast.makeText(
- this,
- getResources().getString(R.string.toast_cannot_write_system_settings),
- Toast.LENGTH_SHORT)
- .show();
- startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
- return;
+ getSupportFragmentManager().addOnBackStackChangedListener(() -> {
+ if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
+ setTitle(R.string.dialer_settings_label);
}
- }
- super.onHeaderClick(header, position);
+ });
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- onBackPressed();
- return true;
- }
- return false;
- }
-
- @Override
- public void onBackPressed() {
- if (!isSafeToCommitTransactions()) {
- return;
- }
- super.onBackPressed();
- }
-
- @Override
- protected boolean isValidFragment(String fragmentName) {
+ public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat caller,
+ @NonNull Preference pref) {
+ Fragment fragment = getSupportFragmentManager()
+ .getFragmentFactory()
+ .instantiate(getClassLoader(), pref.getFragment());
+ fragment.setArguments(pref.getExtras());
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.content_frame, fragment, "")
+ .addToBackStack(null)
+ .commit();
+ setTitle(pref.getTitle());
return true;
}
- /** @return Whether the current user is the primary user. */
- private boolean isPrimaryUser() {
- return getSystemService(UserManager.class).isSystemUser();
+ public static class PrefsFragment extends PreferenceFragmentCompat implements
+ Preference.OnPreferenceClickListener {
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ setPreferenceScreen(getPreferenceManager().createPreferenceScreen(requireContext()));
+
+ if (showDisplayOptions()) {
+ Preference displayOptions = new Preference(getContext());
+ displayOptions.setTitle(R.string.display_options_title);
+ displayOptions.setFragment(DisplayOptionsSettingsFragment.class.getName());
+ getPreferenceScreen().addPreference(displayOptions);
+ }
+
+ Preference soundSettings = new Preference(getContext());
+ soundSettings.setTitle(R.string.sounds_and_vibration_title);
+ soundSettings.setFragment(SoundSettingsFragment.class.getName());
+ soundSettings.setViewId(R.id.settings_header_sounds_and_vibration);
+ getPreferenceScreen().addPreference(soundSettings);
+
+ Preference quickResponseSettings = new Preference(getContext());
+ Intent quickResponseSettingsIntent =
+ new Intent(TelecomManager.ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS);
+ quickResponseSettings.setTitle(R.string.respond_via_sms_setting_title);
+ quickResponseSettings.setIntent(quickResponseSettingsIntent);
+ getPreferenceScreen().addPreference(quickResponseSettings);
+
+ final Preference lookupSettings = new Preference(getContext());
+ lookupSettings.setTitle(R.string.lookup_settings_label);
+ lookupSettings.setFragment(LookupSettingsFragment.class.getName());
+ getPreferenceScreen().addPreference(lookupSettings);
+
+ TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
+ TelecomManager telecomManager = (TelecomManager) getContext().getSystemService(
+ Context.TELECOM_SERVICE);
+
+ // "Call Settings" (full settings) is shown if the current user is primary user and there
+ // is only one SIM. Otherwise, "Calling accounts" is shown.
+ boolean isPrimaryUser = isPrimaryUser();
+ if (isPrimaryUser && TelephonyManagerCompat.getPhoneCount(telephonyManager) <= 1) {
+ Preference callSettings = new Preference(getContext());
+ Intent callSettingsIntent = new Intent(TelecomManager.ACTION_SHOW_CALL_SETTINGS);
+ callSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ callSettings.setTitle(R.string.call_settings_label);
+ callSettings.setIntent(callSettingsIntent);
+ getPreferenceScreen().addPreference(callSettings);
+ } else {
+ Preference phoneAccountSettings = new Preference(getContext());
+ Intent phoneAccountSettingsIntent = new Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS);
+ phoneAccountSettingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ phoneAccountSettings.setTitle(R.string.phone_account_settings_label);
+ phoneAccountSettings.setIntent(phoneAccountSettingsIntent);
+ getPreferenceScreen().addPreference(phoneAccountSettings);
+ }
+ if (BlockedNumberContract.canCurrentUserBlockNumbers(getContext())) {
+ Preference blockedCalls = new Preference(getContext());
+ blockedCalls.setTitle(R.string.manage_blocked_numbers_label);
+ blockedCalls.setIntent(getContext().getSystemService(TelecomManager.class)
+ .createManageBlockedNumbersIntent());
+ getPreferenceScreen().addPreference(blockedCalls);
+ }
+
+ addVoicemailSettings(isPrimaryUser);
+
+ if (isPrimaryUser
+ && (TelephonyManagerCompat.isTtyModeSupported(telecomManager)
+ || TelephonyManagerCompat.isHearingAidCompatibilitySupported(telephonyManager))) {
+ Preference accessibilitySettings = new Preference(getContext());
+ Intent accessibilitySettingsIntent =
+ new Intent(TelecomManager.ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS);
+ accessibilitySettings.setTitle(R.string.accessibility_settings_title);
+ accessibilitySettings.setIntent(accessibilitySettingsIntent);
+ getPreferenceScreen().addPreference(accessibilitySettings);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceClick(@NonNull Preference preference) {
+ if (preference.getTitle().equals(getString(R.string.sounds_and_vibration_title))) {
+ // If we don't have the permission to write to system settings, go to system sound
+ // settings instead. Otherwise, perform the super implementation (which launches our
+ // own preference fragment.
+ if (!Settings.System.canWrite(getContext())) {
+ Toast.makeText(getContext(),
+ getResources().getString(R.string.toast_cannot_write_system_settings),
+ Toast.LENGTH_SHORT)
+ .show();
+ startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
+ return true;
+ }
+ }
+ super.onPreferenceTreeClick(preference);
+ return false;
+ }
+
+ private void addVoicemailSettings(boolean isPrimaryUser) {
+ if (!isPrimaryUser) {
+ LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "user not primary user");
+ return;
+ }
+
+ if (!PermissionsUtil.hasReadPhoneStatePermissions(getContext())) {
+ LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "Missing READ_PHONE_STATE");
+ return;
+ }
+
+ LogUtil.i("DialerSettingsActivity.addVoicemailSettings", "adding voicemail settings");
+ Preference voicemailSettings = new Preference(getContext());
+ voicemailSettings.setTitle(R.string.voicemail_settings_label);
+ Bundle bundle = new Bundle();
+ PhoneAccountHandle soleAccount = getSoleSimAccount();
+ if (soleAccount == null) {
+ LogUtil.i("DialerSettingsActivity.addVoicemailSettings",
+ "showing multi-SIM voicemail settings");
+ voicemailSettings.setFragment(PhoneAccountSelectionFragment.class.getName());
+ bundle.putString(
+ PhoneAccountSelectionFragment.PARAM_TARGET_FRAGMENT,
+ VoicemailSettingsFragment.class.getName());
+ bundle.putString(
+ PhoneAccountSelectionFragment.PARAM_PHONE_ACCOUNT_HANDLE_KEY,
+ VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE);
+ bundle.putBundle(PhoneAccountSelectionFragment.PARAM_ARGUMENTS, new Bundle());
+ bundle.putInt(PhoneAccountSelectionFragment.PARAM_TARGET_TITLE_RES,
+ R.string.voicemail_settings_label);
+ } else {
+ LogUtil.i(
+ "DialerSettingsActivity.addVoicemailSettings", "showing single-SIM voicemail settings");
+ voicemailSettings.setFragment(VoicemailSettingsFragment.class.getName());
+ bundle.putParcelable(VoicemailClient.PARAM_PHONE_ACCOUNT_HANDLE, soleAccount);
+ }
+ voicemailSettings.getExtras().putAll(bundle);
+ getPreferenceScreen().addPreference(voicemailSettings);
+ }
+
+ /**
+ * @return the only SIM phone account, or {@code null} if there are none or more than one. Note:
+ * having a empty SIM slot still count as a PhoneAccountHandle that is "invalid", and
+ * voicemail settings should still be available for it.
+ */
+ @SuppressLint("MissingPermission")
+ @Nullable
+ private PhoneAccountHandle getSoleSimAccount() {
+ TelecomManager telecomManager = requireContext().getSystemService(TelecomManager.class);
+ PhoneAccountHandle result = null;
+ for (PhoneAccountHandle phoneAccountHandle : telecomManager.getCallCapablePhoneAccounts()) {
+ PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle);
+ if (phoneAccount == null) {
+ continue;
+ }
+ if (phoneAccount.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
+ LogUtil.i(
+ "DialerSettingsActivity.getSoleSimAccount", phoneAccountHandle + " is a SIM account");
+ if (result != null) {
+ return null;
+ }
+ result = phoneAccountHandle;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns {@code true} or {@code false} based on whether the display options setting should be
+ * shown. For languages such as Chinese, Japanese, or Korean, display options aren't useful since
+ * contacts are sorted and displayed family name first by default.
+ *
+ * @return {@code true} if the display options should be shown, {@code false} otherwise.
+ */
+ private boolean showDisplayOptions() {
+ return getResources().getBoolean(R.bool.config_display_order_user_changeable)
+ && getResources().getBoolean(R.bool.config_sort_order_user_changeable);
+ }
+
+ /**
+ * @return Whether the current user is the primary user.
+ */
+ private boolean isPrimaryUser() {
+ return requireContext().getSystemService(UserManager.class).isSystemUser();
+ }
}
}
diff --git a/java/com/android/dialer/app/settings/DisplayOptionsSettingsFragment.java b/java/com/android/dialer/app/settings/DisplayOptionsSettingsFragment.java
index 4a3e545..93853ae 100644
--- a/java/com/android/dialer/app/settings/DisplayOptionsSettingsFragment.java
+++ b/java/com/android/dialer/app/settings/DisplayOptionsSettingsFragment.java
@@ -20,10 +20,11 @@
import android.os.Bundle;
import androidx.annotation.Nullable;
+import androidx.preference.PreferenceFragmentCompat;
import com.android.dialer.R;
-public class DisplayOptionsSettingsFragment extends DialerPreferenceFragment {
+public class DisplayOptionsSettingsFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
diff --git a/java/com/android/dialer/app/settings/PhoneAccountSelectionFragment.java b/java/com/android/dialer/app/settings/PhoneAccountSelectionFragment.java
index 28b1bfd..01073b3 100644
--- a/java/com/android/dialer/app/settings/PhoneAccountSelectionFragment.java
+++ b/java/com/android/dialer/app/settings/PhoneAccountSelectionFragment.java
@@ -17,27 +17,29 @@
package com.android.dialer.app.settings;
-import android.app.Fragment;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
+import com.android.dialer.R;
+
import java.util.List;
/**
* Preference screen that lists SIM phone accounts to select from, and forwards the selected account
- * to {@link #PARAM_TARGET_FRAGMENT}. Can only be used in a {@link PreferenceActivity}
+ * to {@link #PARAM_TARGET_FRAGMENT}.
*/
-public class PhoneAccountSelectionFragment extends DialerPreferenceFragment {
+public class PhoneAccountSelectionFragment extends PreferenceFragmentCompat {
/** The {@link PreferenceFragmentCompat} to launch after the account is selected. */
public static final String PARAM_TARGET_FRAGMENT = "target_fragment";
@@ -45,7 +47,7 @@
/**
* The arguments bundle to pass to the {@link #PARAM_TARGET_FRAGMENT}
*
- * @see Fragment#getArguments()
+ * @see PreferenceFragmentCompat#getArguments()
*/
public static final String PARAM_ARGUMENTS = "arguments";
@@ -55,8 +57,7 @@
public static final String PARAM_PHONE_ACCOUNT_HANDLE_KEY = "phone_account_handle_key";
/**
- * The title of the {@link #PARAM_TARGET_FRAGMENT} once it is launched with {@link
- * PreferenceActivity#startWithFragment(String, Bundle, Fragment, int)}, as a string resource ID.
+ * The title of the {@link #PARAM_TARGET_FRAGMENT} once it is launched, as a string resource ID.
*/
public static final String PARAM_TARGET_TITLE_RES = "target_title_res";
@@ -98,10 +99,16 @@
@Override
protected void onClick() {
super.onClick();
- // TODO BadDaemon: fix this
- /*PreferenceActivity preferenceActivity = (PreferenceActivity) getActivity();
+ Fragment fragment = getChildFragmentManager()
+ .getFragmentFactory()
+ .instantiate(getActivity().getClassLoader(), targetFragment);
arguments.putParcelable(phoneAccountHandleKey, phoneAccountHandle);
- preferenceActivity.startWithFragment(targetFragment, arguments, null, 0, titleRes, 0);*/
+ fragment.setArguments(arguments);
+ getParentFragmentManager().beginTransaction()
+ .replace(R.id.content_frame, fragment)
+ .addToBackStack(null)
+ .commit();
+ setTitle(titleRes);
}
}
diff --git a/java/com/android/dialer/app/settings/SoundSettingsFragment.java b/java/com/android/dialer/app/settings/SoundSettingsFragment.java
index 8e12149..2148f2b 100644
--- a/java/com/android/dialer/app/settings/SoundSettingsFragment.java
+++ b/java/com/android/dialer/app/settings/SoundSettingsFragment.java
@@ -17,13 +17,18 @@
package com.android.dialer.app.settings;
+import static android.app.Activity.RESULT_OK;
+
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.Vibrator;
import android.provider.Settings;
@@ -31,9 +36,12 @@
import android.telephony.TelephonyManager;
import android.widget.Toast;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreferenceCompat;
@@ -41,7 +49,7 @@
import com.android.dialer.callrecord.impl.CallRecorderService;
import com.android.dialer.util.SettingsUtil;
-public class SoundSettingsFragment extends DialerPreferenceFragment
+public class SoundSettingsFragment extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener {
private static final int NO_DTMF_TONE = 0;
@@ -54,7 +62,7 @@
private static final int MSG_UPDATE_RINGTONE_SUMMARY = 1;
- private Preference ringtonePreference;
+ private DefaultRingtonePreference ringtonePreference;
private final Handler ringtoneLookupComplete =
new Handler(Looper.getMainLooper()) {
@Override
@@ -68,6 +76,18 @@
};
private final Runnable ringtoneLookupRunnable = () -> updateRingtonePreferenceSummary();
+ private final ActivityResultLauncher<Intent> mRingtonePickerResult = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(), result -> {
+ if (result.getResultCode() == RESULT_OK) {
+ Intent data = result.getData();
+ if (data == null || data.getExtras() == null) {
+ return;
+ }
+ Uri uri = (Uri) data.getExtras().get(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
+ ringtonePreference.onSaveRingtone(uri);
+ }
+ });
+
private SwitchPreferenceCompat vibrateWhenRinging;
private SwitchPreferenceCompat playDtmfTone;
private ListPreference dtmfToneLength;
@@ -221,7 +241,9 @@
.show();
return true;
}
- if (preference == playDtmfTone) {
+ if (preference == ringtonePreference) {
+ mRingtonePickerResult.launch(ringtonePreference.getRingtonePickerIntent());
+ } else if (preference == playDtmfTone) {
Settings.System.putInt(
getActivity().getContentResolver(),
Settings.System.DTMF_TONE_WHEN_DIALING,
@@ -249,7 +271,7 @@
private boolean shouldVibrateWhenRinging() {
int vibrateWhenRingingSetting =
Settings.System.getInt(
- getActivity().getContentResolver(),
+ requireActivity().getContentResolver(),
Settings.System.VIBRATE_WHEN_RINGING,
NO_VIBRATION_FOR_CALLS);
return hasVibrator() && (vibrateWhenRingingSetting == DO_VIBRATION_FOR_CALLS);
@@ -259,7 +281,7 @@
private boolean shouldPlayDtmfTone() {
int dtmfToneSetting =
Settings.System.getInt(
- getActivity().getContentResolver(),
+ requireActivity().getContentResolver(),
Settings.System.DTMF_TONE_WHEN_DIALING,
PLAY_DTMF_TONE);
return dtmfToneSetting == PLAY_DTMF_TONE;
@@ -267,13 +289,14 @@
/** Whether the device hardware has a vibrator. */
private boolean hasVibrator() {
- Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
+ Vibrator vibrator = requireActivity().getSystemService(Vibrator.class);
return vibrator != null && vibrator.hasVibrator();
}
+ @SuppressLint("MissingPermission")
private boolean shouldHideCarrierSettings() {
CarrierConfigManager configManager =
- (CarrierConfigManager) getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ (CarrierConfigManager) requireActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE);
return configManager
.getConfig()
.getBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL);
diff --git a/java/com/android/dialer/lookup/LookupSettingsFragment.java b/java/com/android/dialer/lookup/LookupSettingsFragment.java
index 490a5b7..970198e 100644
--- a/java/com/android/dialer/lookup/LookupSettingsFragment.java
+++ b/java/com/android/dialer/lookup/LookupSettingsFragment.java
@@ -23,12 +23,12 @@
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreferenceCompat;
import com.android.dialer.R;
-import com.android.dialer.app.settings.DialerPreferenceFragment;
-public class LookupSettingsFragment extends DialerPreferenceFragment
+public class LookupSettingsFragment extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener {
private static final String KEY_ENABLE_FORWARD_LOOKUP = "enable_forward_lookup";
diff --git a/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java b/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
index 942f396..4c9f0ba 100644
--- a/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
+++ b/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
@@ -30,12 +30,11 @@
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceClickListener;
+import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreferenceCompat;
import com.android.dialer.R;
-import com.android.dialer.app.settings.DialerPreferenceFragment;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.notification.NotificationChannelManager;
@@ -52,7 +51,7 @@
* Fragment for voicemail settings. Requires {@link VoicemailClient#PARAM_PHONE_ACCOUNT_HANDLE} set
* in arguments.
*/
-public class VoicemailSettingsFragment extends DialerPreferenceFragment
+public class VoicemailSettingsFragment extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener, ActivationStateListener {
// Extras copied from com.android.phone.settings.VoicemailSettingsActivity,
@@ -84,6 +83,11 @@
}
@Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+
+ }
+
+ @Override
public void onResume() {
super.onResume();
voicemailClient.addActivationStateListener(this);