1 /* 2 * Copyright (C) 2014 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 package com.android.systemui.qs; 17 18 import android.app.AlertDialog; 19 import android.content.Context; 20 import android.content.DialogInterface; 21 import android.content.res.Configuration; 22 import android.os.Handler; 23 import android.os.Looper; 24 import android.os.Message; 25 import android.util.Log; 26 import android.util.TypedValue; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.view.View.OnClickListener; 30 import android.widget.ImageView; 31 import android.widget.TextView; 32 33 import com.android.systemui.FontSizeUtils; 34 import com.android.systemui.R; 35 import com.android.systemui.statusbar.phone.QSTileHost; 36 import com.android.systemui.statusbar.phone.SystemUIDialog; 37 import com.android.systemui.statusbar.policy.SecurityController; 38 39 public class QSFooter implements OnClickListener, DialogInterface.OnClickListener { 40 protected static final String TAG = "QSFooter"; 41 protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 42 43 private final View mRootView; 44 private final TextView mFooterText; 45 private final ImageView mFooterIcon; 46 private final Context mContext; 47 private final Callback mCallback = new Callback(); 48 49 private SecurityController mSecurityController; 50 private AlertDialog mDialog; 51 private QSTileHost mHost; 52 private Handler mHandler; 53 private final Handler mMainHandler; 54 55 private boolean mIsVisible; 56 private boolean mIsIconVisible; 57 private int mFooterTextId; 58 QSFooter(QSPanel qsPanel, Context context)59 public QSFooter(QSPanel qsPanel, Context context) { 60 mRootView = LayoutInflater.from(context) 61 .inflate(R.layout.quick_settings_footer, qsPanel, false); 62 mRootView.setOnClickListener(this); 63 mFooterText = (TextView) mRootView.findViewById(R.id.footer_text); 64 mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon); 65 mContext = context; 66 mMainHandler = new Handler(); 67 } 68 setHost(QSTileHost host)69 public void setHost(QSTileHost host) { 70 mHost = host; 71 mSecurityController = host.getSecurityController(); 72 mHandler = new H(host.getLooper()); 73 } 74 setListening(boolean listening)75 public void setListening(boolean listening) { 76 if (listening) { 77 mSecurityController.addCallback(mCallback); 78 } else { 79 mSecurityController.removeCallback(mCallback); 80 } 81 } 82 onConfigurationChanged()83 public void onConfigurationChanged() { 84 FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size); 85 } 86 getView()87 public View getView() { 88 return mRootView; 89 } 90 hasFooter()91 public boolean hasFooter() { 92 return mRootView.getVisibility() != View.GONE; 93 } 94 95 @Override onClick(View v)96 public void onClick(View v) { 97 mHandler.sendEmptyMessage(H.CLICK); 98 } 99 handleClick()100 private void handleClick() { 101 mHost.collapsePanels(); 102 // TODO: Delay dialog creation until after panels are collapsed. 103 createDialog(); 104 } 105 refreshState()106 public void refreshState() { 107 mHandler.sendEmptyMessage(H.REFRESH_STATE); 108 } 109 handleRefreshState()110 private void handleRefreshState() { 111 if (mSecurityController.hasDeviceOwner()) { 112 mFooterTextId = R.string.device_owned_footer; 113 mIsVisible = true; 114 mIsIconVisible = false; 115 } else if (mSecurityController.hasProfileOwner()) { 116 mFooterTextId = R.string.profile_owned_footer; 117 mIsVisible = true; 118 mIsIconVisible = false; 119 } else if (mSecurityController.isVpnEnabled()) { 120 mFooterTextId = R.string.vpn_footer; 121 mIsVisible = true; 122 mIsIconVisible = true; 123 } else { 124 mIsVisible = false; 125 mIsIconVisible = false; 126 } 127 mMainHandler.post(mUpdateDisplayState); 128 } 129 130 @Override onClick(DialogInterface dialog, int which)131 public void onClick(DialogInterface dialog, int which) { 132 if (which == DialogInterface.BUTTON_NEGATIVE) { 133 mSecurityController.disconnectFromVpn(); 134 } 135 } 136 createDialog()137 private void createDialog() { 138 mDialog = new SystemUIDialog(mContext); 139 mDialog.setTitle(getTitle()); 140 mDialog.setMessage(getMessage()); 141 mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this); 142 if (mSecurityController.isVpnEnabled()) { 143 mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getNegativeButton(), this); 144 } 145 mDialog.show(); 146 } 147 getNegativeButton()148 private String getNegativeButton() { 149 if (mSecurityController.isLegacyVpn()) { 150 return mContext.getString(R.string.disconnect_vpn); 151 } else { 152 return mContext.getString(R.string.disable_vpn); 153 } 154 } 155 getPositiveButton()156 private String getPositiveButton() { 157 return mContext.getString(R.string.quick_settings_done); 158 } 159 getMessage()160 private String getMessage() { 161 if (mSecurityController.hasDeviceOwner()) { 162 if (mSecurityController.hasProfileOwner()) { 163 if (mSecurityController.isVpnEnabled()) { 164 if (mSecurityController.isLegacyVpn()) { 165 return mContext.getString( 166 R.string.monitoring_description_legacy_vpn_device_and_profile_owned, 167 mSecurityController.getDeviceOwnerName(), 168 mSecurityController.getProfileOwnerName(), 169 mSecurityController.getLegacyVpnName()); 170 } else { 171 return mContext.getString( 172 R.string.monitoring_description_vpn_device_and_profile_owned, 173 mSecurityController.getDeviceOwnerName(), 174 mSecurityController.getProfileOwnerName(), 175 mSecurityController.getVpnApp()); 176 } 177 } else { 178 return mContext.getString( 179 R.string.monitoring_description_device_and_profile_owned, 180 mSecurityController.getDeviceOwnerName(), 181 mSecurityController.getProfileOwnerName()); 182 } 183 } else { 184 if (mSecurityController.isVpnEnabled()) { 185 if (mSecurityController.isLegacyVpn()) { 186 return mContext.getString( 187 R.string.monitoring_description_legacy_vpn_device_owned, 188 mSecurityController.getDeviceOwnerName(), 189 mSecurityController.getLegacyVpnName()); 190 } else { 191 return mContext.getString(R.string.monitoring_description_vpn_device_owned, 192 mSecurityController.getDeviceOwnerName(), 193 mSecurityController.getVpnApp()); 194 } 195 } else { 196 return mContext.getString(R.string.monitoring_description_device_owned, 197 mSecurityController.getDeviceOwnerName()); 198 } 199 } 200 } else if (mSecurityController.hasProfileOwner()) { 201 if (mSecurityController.isVpnEnabled()) { 202 if (mSecurityController.isLegacyVpn()) { 203 return mContext.getString( 204 R.string.monitoring_description_legacy_vpn_profile_owned, 205 mSecurityController.getProfileOwnerName(), 206 mSecurityController.getLegacyVpnName()); 207 } else { 208 return mContext.getString( 209 R.string.monitoring_description_vpn_profile_owned, 210 mSecurityController.getProfileOwnerName(), 211 mSecurityController.getVpnApp()); 212 } 213 } else { 214 return mContext.getString( 215 R.string.monitoring_description_profile_owned, 216 mSecurityController.getProfileOwnerName()); 217 } 218 } else { 219 if (mSecurityController.isLegacyVpn()) { 220 return mContext.getString(R.string.monitoring_description_legacy_vpn, 221 mSecurityController.getLegacyVpnName()); 222 223 } else { 224 return mContext.getString(R.string.monitoring_description_vpn, 225 mSecurityController.getVpnApp()); 226 } 227 } 228 } 229 getTitle()230 private int getTitle() { 231 if (mSecurityController.hasDeviceOwner()) { 232 return R.string.monitoring_title_device_owned; 233 } 234 if (mSecurityController.hasProfileOwner()) { 235 return R.string.monitoring_title_profile_owned; 236 } 237 return R.string.monitoring_title; 238 } 239 240 private final Runnable mUpdateDisplayState = new Runnable() { 241 @Override 242 public void run() { 243 if (mFooterTextId != 0) { 244 mFooterText.setText(mFooterTextId); 245 } 246 mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE); 247 mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE); 248 } 249 }; 250 251 private class Callback implements SecurityController.SecurityControllerCallback { 252 @Override onStateChanged()253 public void onStateChanged() { 254 refreshState(); 255 } 256 } 257 258 private class H extends Handler { 259 private static final int CLICK = 0; 260 private static final int REFRESH_STATE = 1; 261 H(Looper looper)262 private H(Looper looper) { 263 super(looper); 264 } 265 266 @Override handleMessage(Message msg)267 public void handleMessage(Message msg) { 268 String name = null; 269 try { 270 if (msg.what == REFRESH_STATE) { 271 name = "handleRefreshState"; 272 handleRefreshState(); 273 } else if (msg.what == CLICK) { 274 name = "handleClick"; 275 handleClick(); 276 } 277 } catch (Throwable t) { 278 final String error = "Error in " + name; 279 Log.w(TAG, error, t); 280 mHost.warn(error, t); 281 } 282 } 283 } 284 285 } 286