1 /* 2 * Copyright (C) 2018 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 static android.os.UserHandle.USER_SYSTEM; 20 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.support.annotation.VisibleForTesting; 24 import android.support.v7.preference.ListPreference; 25 import android.support.v7.preference.Preference; 26 import android.support.v7.preference.PreferenceScreen; 27 import android.text.TextUtils; 28 import android.view.DisplayCutout; 29 30 import com.android.settings.R; 31 import com.android.settings.core.PreferenceControllerMixin; 32 import com.android.settings.wrapper.OverlayManagerWrapper; 33 import com.android.settings.wrapper.OverlayManagerWrapper.OverlayInfo; 34 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 35 36 import java.util.List; 37 38 public class EmulateDisplayCutoutPreferenceController extends 39 DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, 40 PreferenceControllerMixin { 41 42 private static final String KEY = "display_cutout_emulation"; 43 44 private final OverlayManagerWrapper mOverlayManager; 45 private final boolean mAvailable; 46 47 private ListPreference mPreference; 48 private PackageManager mPackageManager; 49 50 @VisibleForTesting 51 EmulateDisplayCutoutPreferenceController(Context context, PackageManager packageManager, 52 OverlayManagerWrapper overlayManager) { 53 super(context); 54 mOverlayManager = overlayManager; 55 mPackageManager = packageManager; 56 mAvailable = overlayManager != null && getOverlayInfos().length > 0; 57 } 58 59 public EmulateDisplayCutoutPreferenceController(Context context) { 60 this(context, context.getPackageManager(), new OverlayManagerWrapper()); 61 } 62 63 @Override 64 public boolean isAvailable() { 65 return mAvailable; 66 } 67 68 @Override 69 public String getPreferenceKey() { 70 return KEY; 71 } 72 73 @Override 74 public void displayPreference(PreferenceScreen screen) { 75 super.displayPreference(screen); 76 setPreference((ListPreference) screen.findPreference(getPreferenceKey())); 77 } 78 79 @VisibleForTesting 80 void setPreference(ListPreference preference) { 81 mPreference = preference; 82 } 83 84 @Override 85 public boolean onPreferenceChange(Preference preference, Object newValue) { 86 return setEmulationOverlay((String) newValue); 87 } 88 89 private boolean setEmulationOverlay(String packageName) { 90 OverlayInfo[] overlays = getOverlayInfos(); 91 String currentPackageName = null; 92 for (OverlayInfo o : overlays) { 93 if (o.isEnabled()) { 94 currentPackageName = o.packageName; 95 } 96 } 97 98 if (TextUtils.isEmpty(packageName) && TextUtils.isEmpty(currentPackageName) 99 || TextUtils.equals(packageName, currentPackageName)) { 100 // Already set. 101 return true; 102 } 103 104 final boolean result; 105 if (TextUtils.isEmpty(packageName)) { 106 result = mOverlayManager.setEnabled(currentPackageName, false, USER_SYSTEM); 107 } else { 108 result = mOverlayManager.setEnabledExclusiveInCategory(packageName, USER_SYSTEM); 109 } 110 updateState(mPreference); 111 return result; 112 } 113 114 @Override 115 public void updateState(Preference preference) { 116 OverlayInfo[] overlays = getOverlayInfos(); 117 118 CharSequence[] pkgs = new CharSequence[overlays.length + 1]; 119 CharSequence[] labels = new CharSequence[pkgs.length]; 120 121 int current = 0; 122 pkgs[0] = ""; 123 labels[0] = mContext.getString(R.string.display_cutout_emulation_none); 124 125 for (int i = 0; i < overlays.length; i++) { 126 OverlayInfo o = overlays[i]; 127 pkgs[i+1] = o.packageName; 128 if (o.isEnabled()) { 129 current = i+1; 130 } 131 } 132 for (int i = 1; i < pkgs.length; i++) { 133 try { 134 labels[i] = mPackageManager.getApplicationInfo(pkgs[i].toString(), 0) 135 .loadLabel(mPackageManager); 136 } catch (PackageManager.NameNotFoundException e) { 137 labels[i] = pkgs[i]; 138 } 139 } 140 141 mPreference.setEntries(labels); 142 mPreference.setEntryValues(pkgs); 143 mPreference.setValueIndex(current); 144 mPreference.setSummary(labels[current]); 145 } 146 147 private OverlayInfo[] getOverlayInfos() { 148 @SuppressWarnings("unchecked") List<OverlayInfo> overlayInfos = 149 mOverlayManager.getOverlayInfosForTarget("android", USER_SYSTEM); 150 for (int i = overlayInfos.size() - 1; i >= 0; i--) { 151 if (!DisplayCutout.EMULATION_OVERLAY_CATEGORY.equals( 152 overlayInfos.get(i).category)) { 153 overlayInfos.remove(i); 154 } 155 } 156 return overlayInfos.toArray(new OverlayInfo[overlayInfos.size()]); 157 } 158 159 @Override 160 protected void onDeveloperOptionsSwitchDisabled() { 161 super.onDeveloperOptionsSwitchDisabled(); 162 setEmulationOverlay(""); 163 updateState(mPreference); 164 } 165 166 } 167