1 /*
2  * Copyright (C) 2017 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 
17 package com.android.settings.development.qstile;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.PackageManager;
23 import android.content.pm.ResolveInfo;
24 import android.content.pm.ServiceInfo;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
27 import android.service.quicksettings.TileService;
28 import android.util.Log;
29 
30 import androidx.annotation.VisibleForTesting;
31 import androidx.preference.Preference;
32 import androidx.preference.PreferenceScreen;
33 import androidx.preference.SwitchPreference;
34 
35 import com.android.internal.statusbar.IStatusBarService;
36 import com.android.settings.core.BasePreferenceController;
37 
38 import java.util.List;
39 
40 public class DevelopmentTilePreferenceController extends BasePreferenceController {
41 
42     private static final String TAG = "DevTilePrefController";
43     private final OnChangeHandler mOnChangeHandler;
44     private final PackageManager mPackageManager;
45 
DevelopmentTilePreferenceController(Context context, String key)46     public DevelopmentTilePreferenceController(Context context, String key) {
47         super(context, key);
48         mOnChangeHandler = new OnChangeHandler(context);
49         mPackageManager = context.getPackageManager();
50     }
51 
52     @Override
getAvailabilityStatus()53     public int getAvailabilityStatus() {
54         return AVAILABLE;
55     }
56 
57     @Override
displayPreference(PreferenceScreen screen)58     public void displayPreference(PreferenceScreen screen) {
59         super.displayPreference(screen);
60         final Context context = screen.getContext();
61         final Intent intent = new Intent(TileService.ACTION_QS_TILE)
62                 .setPackage(context.getPackageName());
63         final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent,
64                 PackageManager.MATCH_DISABLED_COMPONENTS);
65         for (ResolveInfo info : resolveInfos) {
66             ServiceInfo sInfo = info.serviceInfo;
67             final int enabledSetting = mPackageManager.getComponentEnabledSetting(
68                     new ComponentName(sInfo.packageName, sInfo.name));
69             boolean checked = enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
70                     || ((enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)
71                     && sInfo.enabled);
72 
73             SwitchPreference preference = new SwitchPreference(context);
74             preference.setTitle(sInfo.loadLabel(mPackageManager));
75             preference.setIcon(sInfo.icon);
76             preference.setKey(sInfo.name);
77             preference.setChecked(checked);
78             preference.setOnPreferenceChangeListener(mOnChangeHandler);
79             screen.addPreference(preference);
80         }
81     }
82 
83     @VisibleForTesting
84     static class OnChangeHandler implements Preference.OnPreferenceChangeListener {
85 
86         private final Context mContext;
87         private final PackageManager mPackageManager;
88         private IStatusBarService mStatusBarService;
89 
OnChangeHandler(Context context)90         public OnChangeHandler(Context context) {
91             mContext = context;
92             mPackageManager = context.getPackageManager();
93             mStatusBarService = IStatusBarService.Stub.asInterface(
94                     ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
95         }
96 
97         @Override
onPreferenceChange(Preference preference, Object newValue)98         public boolean onPreferenceChange(Preference preference, Object newValue) {
99             boolean enabled = ((Boolean) newValue).booleanValue();
100             ComponentName componentName = new ComponentName(
101                     mContext.getPackageName(), preference.getKey());
102             mPackageManager.setComponentEnabledSetting(componentName, enabled
103                             ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
104                             : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
105                     PackageManager.DONT_KILL_APP);
106 
107             try {
108                 if (mStatusBarService != null) {
109                     if (enabled) {
110                         mStatusBarService.addTile(componentName);
111                     } else {
112                         mStatusBarService.remTile(componentName);
113                     }
114                 }
115             } catch (RemoteException e) {
116                 Log.e(TAG, "Failed to modify QS tile for component " +
117                         componentName.toString(), e);
118             }
119             return true;
120         }
121     }
122 }
123