blob: c9bd32b0866a6944adc30a061d8ca7f72827b835 [file] [log] [blame]
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher3;
18
Sunny Goyalba406e22018-04-02 11:36:12 -070019import android.annotation.TargetApi;
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070020import android.app.Activity;
Sunny Goyal848cad52017-07-07 03:12:21 -070021import android.app.AlertDialog;
22import android.app.Dialog;
23import android.app.DialogFragment;
24import android.app.FragmentManager;
25import android.content.ComponentName;
Sunny Goyalf48e5922016-05-12 15:36:20 -070026import android.content.ContentResolver;
Sunny Goyal848cad52017-07-07 03:12:21 -070027import android.content.Context;
28import android.content.DialogInterface;
29import android.content.Intent;
Sunny Goyalba406e22018-04-02 11:36:12 -070030import android.os.Build;
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070031import android.os.Bundle;
Sunny Goyalca187462017-03-31 20:09:34 -070032import android.preference.ListPreference;
Rahul Chaturvedi799aa042015-06-01 21:26:41 -040033import android.preference.Preference;
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070034import android.preference.PreferenceFragment;
Sunny Goyalba406e22018-04-02 11:36:12 -070035import android.preference.PreferenceScreen;
Sunny Goyalf48e5922016-05-12 15:36:20 -070036import android.provider.Settings;
Sunny Goyal3fbca152017-11-02 18:55:44 -070037import android.text.TextUtils;
Sunny Goyal3fbca152017-11-02 18:55:44 -070038import android.view.View;
Sunny Goyal3fbca152017-11-02 18:55:44 -070039import android.widget.Adapter;
Sunny Goyalba406e22018-04-02 11:36:12 -070040import android.widget.ListView;
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070041
Sunny Goyalca187462017-03-31 20:09:34 -070042import com.android.launcher3.graphics.IconShapeOverride;
Sunny Goyal848cad52017-07-07 03:12:21 -070043import com.android.launcher3.notification.NotificationListener;
Sunny Goyalba406e22018-04-02 11:36:12 -070044import com.android.launcher3.util.ListViewHighlighter;
Tonyd48710c2017-07-27 23:23:58 -070045import com.android.launcher3.util.SettingsObserver;
Sunny Goyal848cad52017-07-07 03:12:21 -070046import com.android.launcher3.views.ButtonPreference;
Sunny Goyalba406e22018-04-02 11:36:12 -070047
48import java.util.Objects;
Sunny Goyalca187462017-03-31 20:09:34 -070049
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070050/**
Rahul Chaturvedi799aa042015-06-01 21:26:41 -040051 * Settings activity for Launcher. Currently implements the following setting: Allow rotation
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070052 */
53public class SettingsActivity extends Activity {
Tony Wickham2ab84822017-05-12 14:59:09 -070054
55 private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging";
Tonyd48710c2017-07-27 23:23:58 -070056 /** Hidden field Settings.Secure.NOTIFICATION_BADGING */
57 public static final String NOTIFICATION_BADGING = "notification_badging";
Sunny Goyal848cad52017-07-07 03:12:21 -070058 /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */
59 private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners";
Tony Wickham2ab84822017-05-12 14:59:09 -070060
Sunny Goyal3fbca152017-11-02 18:55:44 -070061 private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
62 private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
63 private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
64
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070065 @Override
66 protected void onCreate(Bundle savedInstanceState) {
67 super.onCreate(savedInstanceState);
68
Mario Bertschler2de2d672017-06-30 18:51:46 -070069 if (savedInstanceState == null) {
70 // Display the fragment as the main content.
71 getFragmentManager().beginTransaction()
Sunny Goyal3fbca152017-11-02 18:55:44 -070072 .replace(android.R.id.content, getNewFragment())
Mario Bertschler2de2d672017-06-30 18:51:46 -070073 .commit();
74 }
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070075 }
76
Sunny Goyal3fbca152017-11-02 18:55:44 -070077 protected PreferenceFragment getNewFragment() {
78 return new LauncherSettingsFragment();
79 }
80
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070081 /**
82 * This fragment shows the launcher preferences.
83 */
Sunny Goyalf48e5922016-05-12 15:36:20 -070084 public static class LauncherSettingsFragment extends PreferenceFragment {
85
Tony Wickham2ab84822017-05-12 14:59:09 -070086 private IconBadgingObserver mIconBadgingObserver;
Sunny Goyalf48e5922016-05-12 15:36:20 -070087
Sunny Goyal3fbca152017-11-02 18:55:44 -070088 private String mPreferenceKey;
89 private boolean mPreferenceHighlighted = false;
90
91 @Override
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070092 public void onCreate(Bundle savedInstanceState) {
93 super.onCreate(savedInstanceState);
Sunny Goyal3fbca152017-11-02 18:55:44 -070094 if (savedInstanceState != null) {
95 mPreferenceHighlighted = savedInstanceState.getBoolean(SAVE_HIGHLIGHTED_KEY);
96 }
97
Sunny Goyalf48e5922016-05-12 15:36:20 -070098 getPreferenceManager().setSharedPreferencesName(LauncherFiles.SHARED_PREFERENCES_KEY);
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -070099 addPreferencesFromResource(R.xml.launcher_preferences);
Sunny Goyal7779d622015-06-11 16:18:39 -0700100
Tony Wickham2ab84822017-05-12 14:59:09 -0700101 ContentResolver resolver = getActivity().getContentResolver();
102
Sunny Goyal848cad52017-07-07 03:12:21 -0700103 ButtonPreference iconBadgingPref =
104 (ButtonPreference) findPreference(ICON_BADGING_PREFERENCE_KEY);
Hyunyoung Songe24cb632017-09-11 11:18:03 -0700105 if (!Utilities.ATLEAST_OREO) {
Sunny Goyal4179e9b2017-03-08 14:25:09 -0800106 getPreferenceScreen().removePreference(
107 findPreference(SessionCommitReceiver.ADD_ICON_PREFERENCE_KEY));
Tony Wickham2ab84822017-05-12 14:59:09 -0700108 getPreferenceScreen().removePreference(iconBadgingPref);
Tony Wickhamc1385152017-08-14 14:31:03 -0700109 } else if (!getResources().getBoolean(R.bool.notification_badging_enabled)) {
110 getPreferenceScreen().removePreference(iconBadgingPref);
Tony Wickham2ab84822017-05-12 14:59:09 -0700111 } else {
112 // Listen to system notification badge settings while this UI is active.
Sunny Goyal848cad52017-07-07 03:12:21 -0700113 mIconBadgingObserver = new IconBadgingObserver(
114 iconBadgingPref, resolver, getFragmentManager());
Tonyd48710c2017-07-27 23:23:58 -0700115 mIconBadgingObserver.register(NOTIFICATION_BADGING, NOTIFICATION_ENABLED_LISTENERS);
Sunny Goyal4179e9b2017-03-08 14:25:09 -0800116 }
Sunny Goyalca187462017-03-31 20:09:34 -0700117
118 Preference iconShapeOverride = findPreference(IconShapeOverride.KEY_PREFERENCE);
119 if (iconShapeOverride != null) {
120 if (IconShapeOverride.isSupported(getActivity())) {
121 IconShapeOverride.handlePreferenceUi((ListPreference) iconShapeOverride);
122 } else {
123 getPreferenceScreen().removePreference(iconShapeOverride);
124 }
125 }
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -0700126 }
Rahul Chaturvedi799aa042015-06-01 21:26:41 -0400127
128 @Override
Sunny Goyal3fbca152017-11-02 18:55:44 -0700129 public void onSaveInstanceState(Bundle outState) {
130 super.onSaveInstanceState(outState);
131 outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mPreferenceHighlighted);
132 }
133
134 @Override
135 public void onResume() {
136 super.onResume();
137
138 Intent intent = getActivity().getIntent();
139 mPreferenceKey = intent.getStringExtra(EXTRA_FRAGMENT_ARG_KEY);
140 if (isAdded() && !mPreferenceHighlighted && !TextUtils.isEmpty(mPreferenceKey)) {
141 getView().postDelayed(this::highlightPreference, DELAY_HIGHLIGHT_DURATION_MILLIS);
142 }
143 }
144
145 private void highlightPreference() {
Sunny Goyal3fbca152017-11-02 18:55:44 -0700146 Preference pref = findPreference(mPreferenceKey);
Sunny Goyalba406e22018-04-02 11:36:12 -0700147 if (pref == null || getPreferenceScreen() == null) {
Sunny Goyal3fbca152017-11-02 18:55:44 -0700148 return;
149 }
Sunny Goyalba406e22018-04-02 11:36:12 -0700150 PreferenceScreen screen = getPreferenceScreen();
151 if (Utilities.ATLEAST_OREO) {
152 screen = selectPreferenceRecursive(pref, screen);
153 }
154 if (screen == null) {
155 return;
156 }
157
158 View root = screen.getDialog() != null
159 ? screen.getDialog().getWindow().getDecorView() : getView();
160 ListView list = root.findViewById(android.R.id.list);
161 if (list == null || list.getAdapter() == null) {
162 return;
163 }
164 Adapter adapter = list.getAdapter();
Sunny Goyal3fbca152017-11-02 18:55:44 -0700165
166 // Find the position
167 int position = -1;
168 for (int i = adapter.getCount() - 1; i >= 0; i--) {
169 if (pref == adapter.getItem(i)) {
170 position = i;
171 break;
172 }
173 }
Sunny Goyalba406e22018-04-02 11:36:12 -0700174 new ListViewHighlighter(list, position);
Sunny Goyal3fbca152017-11-02 18:55:44 -0700175 mPreferenceHighlighted = true;
176 }
177
178 @Override
Sunny Goyalf48e5922016-05-12 15:36:20 -0700179 public void onDestroy() {
Tony Wickham2ab84822017-05-12 14:59:09 -0700180 if (mIconBadgingObserver != null) {
Tonyd48710c2017-07-27 23:23:58 -0700181 mIconBadgingObserver.unregister();
Tony Wickham2ab84822017-05-12 14:59:09 -0700182 mIconBadgingObserver = null;
183 }
Sunny Goyalf48e5922016-05-12 15:36:20 -0700184 super.onDestroy();
185 }
Sunny Goyalba406e22018-04-02 11:36:12 -0700186
187 @TargetApi(Build.VERSION_CODES.O)
188 private PreferenceScreen selectPreferenceRecursive(
189 Preference pref, PreferenceScreen topParent) {
190 if (!(pref.getParent() instanceof PreferenceScreen)) {
191 return null;
192 }
193
194 PreferenceScreen parent = (PreferenceScreen) pref.getParent();
195 if (Objects.equals(parent.getKey(), topParent.getKey())) {
196 return parent;
197 } else if (selectPreferenceRecursive(parent, topParent) != null) {
198 ((PreferenceScreen) parent.getParent())
199 .onItemClick(null, null, parent.getOrder(), 0);
200 return parent;
201 } else {
202 return null;
203 }
204 }
Sunny Goyalf48e5922016-05-12 15:36:20 -0700205 }
206
207 /**
Tony Wickham2ab84822017-05-12 14:59:09 -0700208 * Content observer which listens for system badging setting changes,
209 * and updates the launcher badging setting subtext accordingly.
210 */
Tonyd48710c2017-07-27 23:23:58 -0700211 private static class IconBadgingObserver extends SettingsObserver.Secure
Sunny Goyalb65e13c2017-08-01 11:04:15 -0700212 implements Preference.OnPreferenceClickListener {
Tony Wickham2ab84822017-05-12 14:59:09 -0700213
Sunny Goyal848cad52017-07-07 03:12:21 -0700214 private final ButtonPreference mBadgingPref;
Tony Wickham2ab84822017-05-12 14:59:09 -0700215 private final ContentResolver mResolver;
Sunny Goyal848cad52017-07-07 03:12:21 -0700216 private final FragmentManager mFragmentManager;
Tony Wickham2ab84822017-05-12 14:59:09 -0700217
Sunny Goyal848cad52017-07-07 03:12:21 -0700218 public IconBadgingObserver(ButtonPreference badgingPref, ContentResolver resolver,
219 FragmentManager fragmentManager) {
Tonyd48710c2017-07-27 23:23:58 -0700220 super(resolver);
Tony Wickham2ab84822017-05-12 14:59:09 -0700221 mBadgingPref = badgingPref;
222 mResolver = resolver;
Sunny Goyal848cad52017-07-07 03:12:21 -0700223 mFragmentManager = fragmentManager;
Tony Wickham2ab84822017-05-12 14:59:09 -0700224 }
225
226 @Override
Tonyd48710c2017-07-27 23:23:58 -0700227 public void onSettingChanged(boolean enabled) {
Sunny Goyal848cad52017-07-07 03:12:21 -0700228 int summary = enabled ? R.string.icon_badging_desc_on : R.string.icon_badging_desc_off;
229
230 boolean serviceEnabled = true;
231 if (enabled) {
232 // Check if the listener is enabled or not.
233 String enabledListeners =
234 Settings.Secure.getString(mResolver, NOTIFICATION_ENABLED_LISTENERS);
235 ComponentName myListener =
236 new ComponentName(mBadgingPref.getContext(), NotificationListener.class);
237 serviceEnabled = enabledListeners != null &&
238 (enabledListeners.contains(myListener.flattenToString()) ||
239 enabledListeners.contains(myListener.flattenToShortString()));
240 if (!serviceEnabled) {
241 summary = R.string.title_missing_notification_access;
242 }
243 }
Sunny Goyalb65e13c2017-08-01 11:04:15 -0700244 mBadgingPref.setWidgetFrameVisible(!serviceEnabled);
245 mBadgingPref.setOnPreferenceClickListener(serviceEnabled ? null : this);
Sunny Goyal848cad52017-07-07 03:12:21 -0700246 mBadgingPref.setSummary(summary);
247
248 }
249
250 @Override
Sunny Goyalb65e13c2017-08-01 11:04:15 -0700251 public boolean onPreferenceClick(Preference preference) {
Sunny Goyal848cad52017-07-07 03:12:21 -0700252 new NotificationAccessConfirmation().show(mFragmentManager, "notification_access");
Sunny Goyalb65e13c2017-08-01 11:04:15 -0700253 return true;
Tony Wickham2ab84822017-05-12 14:59:09 -0700254 }
255 }
256
Sunny Goyal848cad52017-07-07 03:12:21 -0700257 public static class NotificationAccessConfirmation
258 extends DialogFragment implements DialogInterface.OnClickListener {
259
260 @Override
261 public Dialog onCreateDialog(Bundle savedInstanceState) {
262 final Context context = getActivity();
263 String msg = context.getString(R.string.msg_missing_notification_access,
264 context.getString(R.string.derived_app_name));
265 return new AlertDialog.Builder(context)
266 .setTitle(R.string.title_missing_notification_access)
267 .setMessage(msg)
268 .setNegativeButton(android.R.string.cancel, null)
269 .setPositiveButton(R.string.title_change_settings, this)
270 .create();
271 }
272
273 @Override
274 public void onClick(DialogInterface dialogInterface, int i) {
275 ComponentName cn = new ComponentName(getActivity(), NotificationListener.class);
276 Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)
277 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
278 .putExtra(":settings:fragment_args_key", cn.flattenToString());
279 getActivity().startActivity(intent);
280 }
281 }
Rahul Chaturvedi7fc77ca2015-05-19 18:02:16 -0700282}