Home | History | Annotate | Download | only in qs
      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.Intent;
     22 import android.os.Handler;
     23 import android.os.Looper;
     24 import android.os.Message;
     25 import android.os.UserHandle;
     26 import android.util.Log;
     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 static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
     44 
     45     private final View mRootView;
     46     private final TextView mFooterText;
     47     private final ImageView mFooterIcon;
     48     private final Context mContext;
     49     private final Callback mCallback = new Callback();
     50 
     51     private SecurityController mSecurityController;
     52     private AlertDialog mDialog;
     53     private QSTileHost mHost;
     54     private Handler mHandler;
     55     private final Handler mMainHandler;
     56 
     57     private boolean mIsVisible;
     58     private boolean mIsIconVisible;
     59     private int mFooterTextId;
     60 
     61     public QSFooter(QSPanel qsPanel, Context context) {
     62         mRootView = LayoutInflater.from(context)
     63                 .inflate(R.layout.quick_settings_footer, qsPanel, false);
     64         mRootView.setOnClickListener(this);
     65         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
     66         mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
     67         mContext = context;
     68         mMainHandler = new Handler();
     69     }
     70 
     71     public void setHost(QSTileHost host) {
     72         mHost = host;
     73         mSecurityController = host.getSecurityController();
     74         mHandler = new H(host.getLooper());
     75     }
     76 
     77     public void setListening(boolean listening) {
     78         if (listening) {
     79             mSecurityController.addCallback(mCallback);
     80         } else {
     81             mSecurityController.removeCallback(mCallback);
     82         }
     83     }
     84 
     85     public void onConfigurationChanged() {
     86         FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size);
     87     }
     88 
     89     public View getView() {
     90         return mRootView;
     91     }
     92 
     93     public boolean hasFooter() {
     94         return mRootView.getVisibility() != View.GONE;
     95     }
     96 
     97     @Override
     98     public void onClick(View v) {
     99         mHandler.sendEmptyMessage(H.CLICK);
    100     }
    101 
    102     private void handleClick() {
    103         mHost.collapsePanels();
    104         // TODO: Delay dialog creation until after panels are collapsed.
    105         createDialog();
    106     }
    107 
    108     public void refreshState() {
    109         mHandler.sendEmptyMessage(H.REFRESH_STATE);
    110     }
    111 
    112     private void handleRefreshState() {
    113         mIsIconVisible = mSecurityController.isVpnEnabled();
    114         if (mSecurityController.hasDeviceOwner()) {
    115             mFooterTextId = R.string.device_owned_footer;
    116             mIsVisible = true;
    117         } else {
    118             mFooterTextId = R.string.vpn_footer;
    119             mIsVisible = mIsIconVisible;
    120         }
    121         mMainHandler.post(mUpdateDisplayState);
    122     }
    123 
    124     @Override
    125     public void onClick(DialogInterface dialog, int which) {
    126         if (which == DialogInterface.BUTTON_NEGATIVE) {
    127             final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
    128             mContext.startActivityAsUser(settingsIntent, UserHandle.CURRENT);
    129         }
    130     }
    131 
    132     private void createDialog() {
    133         String deviceOwner = mSecurityController.getDeviceOwnerName();
    134         String profileOwner = mSecurityController.getProfileOwnerName();
    135         String primaryVpn = mSecurityController.getPrimaryVpnName();
    136         String profileVpn = mSecurityController.getProfileVpnName();
    137         boolean managed = mSecurityController.hasProfileOwner();
    138 
    139         mDialog = new SystemUIDialog(mContext);
    140         mDialog.setTitle(getTitle(deviceOwner));
    141         mDialog.setMessage(getMessage(deviceOwner, profileOwner, primaryVpn, profileVpn, managed));
    142         mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
    143         if (mSecurityController.isVpnEnabled()) {
    144             mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getNegativeButton(), this);
    145         }
    146         mDialog.show();
    147     }
    148 
    149     private String getNegativeButton() {
    150         return mContext.getString(R.string.status_bar_settings_settings_button);
    151     }
    152 
    153     private String getPositiveButton() {
    154         return mContext.getString(R.string.quick_settings_done);
    155     }
    156 
    157     private String getMessage(String deviceOwner, String profileOwner, String primaryVpn,
    158             String profileVpn, boolean primaryUserIsManaged) {
    159         if (deviceOwner != null) {
    160             if (primaryVpn != null) {
    161                 return mContext.getString(R.string.monitoring_description_vpn_app_device_owned,
    162                         deviceOwner, primaryVpn);
    163             } else {
    164                 return mContext.getString(R.string.monitoring_description_device_owned,
    165                         deviceOwner);
    166             }
    167         } else if (primaryVpn != null) {
    168             if (profileVpn != null) {
    169                 return mContext.getString(R.string.monitoring_description_app_personal_work,
    170                         profileOwner, profileVpn, primaryVpn);
    171             } else {
    172                 return mContext.getString(R.string.monitoring_description_app_personal,
    173                         primaryVpn);
    174             }
    175         } else if (profileVpn != null) {
    176             return mContext.getString(R.string.monitoring_description_app_work,
    177                     profileOwner, profileVpn);
    178         } else if (profileOwner != null && primaryUserIsManaged) {
    179             return mContext.getString(R.string.monitoring_description_device_owned,
    180                     profileOwner);
    181         } else {
    182             // No device owner, no personal VPN, no work VPN, no user owner. Why are we here?
    183             return null;
    184         }
    185     }
    186 
    187     private int getTitle(String deviceOwner) {
    188         if (deviceOwner != null) {
    189             return R.string.monitoring_title_device_owned;
    190         } else {
    191             return R.string.monitoring_title;
    192         }
    193     }
    194 
    195     private final Runnable mUpdateDisplayState = new Runnable() {
    196         @Override
    197         public void run() {
    198             if (mFooterTextId != 0) {
    199                 mFooterText.setText(mFooterTextId);
    200             }
    201             mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
    202             mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
    203         }
    204     };
    205 
    206     private class Callback implements SecurityController.SecurityControllerCallback {
    207         @Override
    208         public void onStateChanged() {
    209             refreshState();
    210         }
    211     }
    212 
    213     private class H extends Handler {
    214         private static final int CLICK = 0;
    215         private static final int REFRESH_STATE = 1;
    216 
    217         private H(Looper looper) {
    218             super(looper);
    219         }
    220 
    221         @Override
    222         public void handleMessage(Message msg) {
    223             String name = null;
    224             try {
    225                 if (msg.what == REFRESH_STATE) {
    226                     name = "handleRefreshState";
    227                     handleRefreshState();
    228                 } else if (msg.what == CLICK) {
    229                     name = "handleClick";
    230                     handleClick();
    231                 }
    232             } catch (Throwable t) {
    233                 final String error = "Error in " + name;
    234                 Log.w(TAG, error, t);
    235                 mHost.warn(error, t);
    236             }
    237         }
    238     }
    239 
    240 }
    241