• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * 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.pm.PackageManager;
22 import android.os.IBinder;
23 import android.os.Parcel;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.os.SystemProperties;
27 import android.provider.Settings;
28 import android.service.quicksettings.Tile;
29 import android.service.quicksettings.TileService;
30 import android.support.annotation.VisibleForTesting;
31 import android.util.EventLog;
32 import android.util.Log;
33 import android.view.IWindowManager;
34 import android.view.ThreadedRenderer;
35 import android.view.View;
36 import android.view.WindowManagerGlobal;
37 import android.widget.Toast;
38 
39 import com.android.internal.app.LocalePicker;
40 import com.android.internal.statusbar.IStatusBarService;
41 import com.android.settingslib.development.DevelopmentSettingsEnabler;
42 import com.android.settingslib.development.SystemPropPoker;
43 
44 public abstract class DevelopmentTiles extends TileService {
45     private static final String TAG = "DevelopmentTiles";
46 
isEnabled()47     protected abstract boolean isEnabled();
48 
setIsEnabled(boolean isEnabled)49     protected abstract void setIsEnabled(boolean isEnabled);
50 
51     @Override
onStartListening()52     public void onStartListening() {
53         super.onStartListening();
54         refresh();
55     }
56 
refresh()57     public void refresh() {
58         final int state;
59         if (!DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)) {
60             // Reset to disabled state if dev option is off.
61             if (isEnabled()) {
62                 setIsEnabled(false);
63                 SystemPropPoker.getInstance().poke();
64             }
65             final ComponentName cn = new ComponentName(getPackageName(), getClass().getName());
66             try {
67                 getPackageManager().setComponentEnabledSetting(
68                         cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
69                         PackageManager.DONT_KILL_APP);
70                 final IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
71                         ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
72                 if (statusBarService != null) {
73                     EventLog.writeEvent(0x534e4554, "117770924");  // SaftyNet
74                     statusBarService.remTile(cn);
75                 }
76             } catch (RemoteException e) {
77                 Log.e(TAG, "Failed to modify QS tile for component " +
78                         cn.toString(), e);
79             }
80             state = Tile.STATE_UNAVAILABLE;
81         } else {
82             state = isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
83         }
84         getQsTile().setState(state);
85         getQsTile().updateTile();
86     }
87 
88     @Override
onClick()89     public void onClick() {
90         setIsEnabled(getQsTile().getState() == Tile.STATE_INACTIVE);
91         SystemPropPoker.getInstance().poke(); // Settings app magic
92         refresh();
93     }
94 
95     /**
96      * Tile to control the "Show layout bounds" developer setting
97      */
98     public static class ShowLayout extends DevelopmentTiles {
99 
100         @Override
isEnabled()101         protected boolean isEnabled() {
102             return SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
103         }
104 
105         @Override
setIsEnabled(boolean isEnabled)106         protected void setIsEnabled(boolean isEnabled) {
107             SystemProperties.set(View.DEBUG_LAYOUT_PROPERTY, isEnabled ? "true" : "false");
108         }
109     }
110 
111     /**
112      * Tile to control the "GPU profiling" developer setting
113      */
114     public static class GPUProfiling extends DevelopmentTiles {
115 
116         @Override
isEnabled()117         protected boolean isEnabled() {
118             final String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
119             return value.equals("visual_bars");
120         }
121 
122         @Override
setIsEnabled(boolean isEnabled)123         protected void setIsEnabled(boolean isEnabled) {
124             SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY, isEnabled ? "visual_bars" : "");
125         }
126     }
127 
128     /**
129      * Tile to control the "Force RTL" developer setting
130      */
131     public static class ForceRTL extends DevelopmentTiles {
132 
133         @Override
isEnabled()134         protected boolean isEnabled() {
135             return Settings.Global.getInt(
136                     getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
137         }
138 
139         @Override
setIsEnabled(boolean isEnabled)140         protected void setIsEnabled(boolean isEnabled) {
141             Settings.Global.putInt(
142                     getContentResolver(), Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? 1 : 0);
143             SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, isEnabled ? "1" : "0");
144             LocalePicker.updateLocales(getResources().getConfiguration().getLocales());
145         }
146     }
147 
148     /**
149      * Tile to control the "Animation speed" developer setting
150      */
151     public static class AnimationSpeed extends DevelopmentTiles {
152 
153         @Override
isEnabled()154         protected boolean isEnabled() {
155             IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
156             try {
157                 return wm.getAnimationScale(0) != 1;
158             } catch (RemoteException e) { }
159             return false;
160         }
161 
162         @Override
setIsEnabled(boolean isEnabled)163         protected void setIsEnabled(boolean isEnabled) {
164             IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
165             float scale = isEnabled ? 10 : 1;
166             try {
167                 wm.setAnimationScale(0, scale);
168                 wm.setAnimationScale(1, scale);
169                 wm.setAnimationScale(2, scale);
170             } catch (RemoteException e) { }
171         }
172     }
173 
174     /**
175      * Tile to toggle Winscope trace which consists of Window and Layer traces.
176      */
177     public static class WinscopeTrace extends DevelopmentTiles {
178         @VisibleForTesting
179         static final int SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE = 1025;
180         @VisibleForTesting
181         static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026;
182         private IBinder mSurfaceFlinger;
183         private IWindowManager mWindowManager;
184         private Toast mToast;
185 
186         @Override
onCreate()187         public void onCreate() {
188             super.onCreate();
189             mWindowManager = WindowManagerGlobal.getWindowManagerService();
190             mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
191             Context context = getApplicationContext();
192             CharSequence text = "Trace files written to /data/misc/wmtrace";
193             mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
194         }
195 
isWindowTraceEnabled()196         private boolean isWindowTraceEnabled() {
197             try {
198                 return mWindowManager.isWindowTraceEnabled();
199             } catch (RemoteException e) {
200                 Log.e(TAG,
201                         "Could not get window trace status, defaulting to false." + e.toString());
202             }
203             return false;
204         }
205 
isLayerTraceEnabled()206         private boolean isLayerTraceEnabled() {
207             boolean layerTraceEnabled = false;
208             Parcel reply = null;
209             Parcel data = null;
210             try {
211                 if (mSurfaceFlinger != null) {
212                     reply = Parcel.obtain();
213                     data = Parcel.obtain();
214                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
215                     mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE,
216                             data, reply, 0 /* flags */);
217                     layerTraceEnabled = reply.readBoolean();
218                 }
219             } catch (RemoteException e) {
220                 Log.e(TAG, "Could not get layer trace status, defaulting to false." + e.toString());
221             } finally {
222                 if (data != null) {
223                     data.recycle();
224                     reply.recycle();
225                 }
226             }
227             return layerTraceEnabled;
228         }
229 
230         @Override
isEnabled()231         protected boolean isEnabled() {
232             return isWindowTraceEnabled() || isLayerTraceEnabled();
233         }
234 
setWindowTraceEnabled(boolean isEnabled)235         private void setWindowTraceEnabled(boolean isEnabled) {
236             try {
237                 if (isEnabled) {
238                     mWindowManager.startWindowTrace();
239                 } else {
240                     mWindowManager.stopWindowTrace();
241                 }
242             } catch (RemoteException e) {
243                 Log.e(TAG, "Could not set window trace status." + e.toString());
244             }
245         }
246 
setLayerTraceEnabled(boolean isEnabled)247         private void setLayerTraceEnabled(boolean isEnabled) {
248             Parcel data = null;
249             try {
250                 if (mSurfaceFlinger != null) {
251                     data = Parcel.obtain();
252                     data.writeInterfaceToken("android.ui.ISurfaceComposer");
253                     data.writeInt(isEnabled ? 1 : 0);
254                     mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE,
255                             data, null, 0 /* flags */);
256                 }
257             } catch (RemoteException e) {
258                 Log.e(TAG, "Could not set layer tracing." + e.toString());
259             } finally {
260                 if (data != null) {
261                     data.recycle();
262                 }
263             }
264         }
265 
266         @Override
setIsEnabled(boolean isEnabled)267         protected void setIsEnabled(boolean isEnabled) {
268             setWindowTraceEnabled(isEnabled);
269             setLayerTraceEnabled(isEnabled);
270             if (!isEnabled) {
271                 mToast.show();
272             }
273         }
274     }
275 }
276