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; 18 19 import android.content.Context; 20 import android.os.IBinder; 21 import android.os.Parcel; 22 import android.os.RemoteException; 23 import android.os.ServiceManager; 24 import android.support.annotation.VisibleForTesting; 25 import android.support.v14.preference.SwitchPreference; 26 import android.support.v7.preference.Preference; 27 28 import com.android.settings.core.PreferenceControllerMixin; 29 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 30 31 public class HardwareOverlaysPreferenceController extends DeveloperOptionsPreferenceController 32 implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { 33 34 private static final String DISABLE_OVERLAYS_KEY = "disable_overlays"; 35 36 private static final int SETTING_VALUE_ON = 1; 37 private static final int SETTING_VALUE_OFF = 0; 38 private static final String SURFACE_FLINGER_SERVICE_KEY = "SurfaceFlinger"; 39 40 @VisibleForTesting 41 static final int SURFACE_FLINGER_READ_CODE = 1010; 42 43 private static final int SURFACE_FLINGER_DISABLE_OVERLAYS_CODE = 1008; 44 private static final String SURFACE_COMPOSER_INTERFACE_KEY = "android.ui.ISurfaceComposer"; 45 46 private final IBinder mSurfaceFlinger; 47 HardwareOverlaysPreferenceController(Context context)48 public HardwareOverlaysPreferenceController(Context context) { 49 super(context); 50 mSurfaceFlinger = ServiceManager.getService(SURFACE_FLINGER_SERVICE_KEY); 51 } 52 53 @Override getPreferenceKey()54 public String getPreferenceKey() { 55 return DISABLE_OVERLAYS_KEY; 56 } 57 58 @Override onPreferenceChange(Preference preference, Object newValue)59 public boolean onPreferenceChange(Preference preference, Object newValue) { 60 final boolean isEnabled = (Boolean) newValue; 61 writeHardwareOverlaysSetting(isEnabled); 62 return true; 63 } 64 65 @Override updateState(Preference preference)66 public void updateState(Preference preference) { 67 updateHardwareOverlaysSetting(); 68 } 69 70 @Override onDeveloperOptionsSwitchDisabled()71 protected void onDeveloperOptionsSwitchDisabled() { 72 super.onDeveloperOptionsSwitchDisabled(); 73 final SwitchPreference switchPreference = (SwitchPreference) mPreference; 74 if (switchPreference.isChecked()) { 75 // Writing false to the preference when the setting is already off will have a 76 // side effect of turning on the preference that we wish to avoid 77 writeHardwareOverlaysSetting(false); 78 switchPreference.setChecked(false); 79 } 80 } 81 82 @VisibleForTesting updateHardwareOverlaysSetting()83 void updateHardwareOverlaysSetting() { 84 if (mSurfaceFlinger == null) { 85 return; 86 } 87 // magic communication with surface flinger. 88 try { 89 final Parcel data = Parcel.obtain(); 90 final Parcel reply = Parcel.obtain(); 91 data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY); 92 mSurfaceFlinger.transact(SURFACE_FLINGER_READ_CODE, data, reply, 0 /* flags */); 93 @SuppressWarnings("unused") final int showCpu = reply.readInt(); 94 @SuppressWarnings("unused") final int enableGL = reply.readInt(); 95 @SuppressWarnings("unused") final int showUpdates = reply.readInt(); 96 @SuppressWarnings("unused") final int showBackground = reply.readInt(); 97 final int disableOverlays = reply.readInt(); 98 ((SwitchPreference) mPreference).setChecked(disableOverlays != SETTING_VALUE_OFF); 99 reply.recycle(); 100 data.recycle(); 101 } catch (RemoteException ex) { 102 // intentional no-op 103 } 104 } 105 106 @VisibleForTesting writeHardwareOverlaysSetting(boolean isEnabled)107 void writeHardwareOverlaysSetting(boolean isEnabled) { 108 if (mSurfaceFlinger == null) { 109 return; 110 } 111 try { 112 final Parcel data = Parcel.obtain(); 113 data.writeInterfaceToken(SURFACE_COMPOSER_INTERFACE_KEY); 114 final int disableOverlays = isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF; 115 data.writeInt(disableOverlays); 116 mSurfaceFlinger.transact(SURFACE_FLINGER_DISABLE_OVERLAYS_CODE, data, 117 null /* reply */, 0 /* flags */); 118 data.recycle(); 119 } catch (RemoteException ex) { 120 // intentional no-op 121 } 122 updateHardwareOverlaysSetting(); 123 } 124 } 125