1 /* 2 * Copyright (C) 2011 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.vpndialogs; 18 19 import android.content.Context; 20 import android.content.DialogInterface; 21 import android.net.IConnectivityManager; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.os.ServiceManager; 25 import android.os.SystemClock; 26 import android.os.UserHandle; 27 import android.util.Log; 28 import android.view.View; 29 import android.widget.TextView; 30 31 import com.android.internal.app.AlertActivity; 32 import com.android.internal.net.VpnConfig; 33 34 import java.io.DataInputStream; 35 import java.io.FileInputStream; 36 37 public class ManageDialog extends AlertActivity implements 38 DialogInterface.OnClickListener, Handler.Callback { 39 private static final String TAG = "VpnManage"; 40 41 private VpnConfig mConfig; 42 43 private IConnectivityManager mService; 44 45 private TextView mDuration; 46 private TextView mDataTransmitted; 47 private TextView mDataReceived; 48 private boolean mDataRowsHidden; 49 50 private Handler mHandler; 51 52 @Override onResume()53 protected void onResume() { 54 super.onResume(); 55 56 if (getCallingPackage() != null) { 57 Log.e(TAG, getCallingPackage() + " cannot start this activity"); 58 finish(); 59 return; 60 } 61 62 try { 63 64 mService = IConnectivityManager.Stub.asInterface( 65 ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 66 67 mConfig = mService.getVpnConfig(UserHandle.myUserId()); 68 69 // mConfig can be null if we are a restricted user, in that case don't show this dialog 70 if (mConfig == null) { 71 finish(); 72 return; 73 } 74 75 View view = View.inflate(this, R.layout.manage, null); 76 if (mConfig.session != null) { 77 ((TextView) view.findViewById(R.id.session)).setText(mConfig.session); 78 } 79 mDuration = (TextView) view.findViewById(R.id.duration); 80 mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted); 81 mDataReceived = (TextView) view.findViewById(R.id.data_received); 82 mDataRowsHidden = true; 83 84 if (mConfig.legacy) { 85 mAlertParams.mTitle = getText(R.string.legacy_title); 86 } else { 87 mAlertParams.mTitle = VpnConfig.getVpnLabel(this, mConfig.user); 88 } 89 if (mConfig.configureIntent != null) { 90 mAlertParams.mPositiveButtonText = getText(R.string.configure); 91 mAlertParams.mPositiveButtonListener = this; 92 } 93 mAlertParams.mNeutralButtonText = getText(R.string.disconnect); 94 mAlertParams.mNeutralButtonListener = this; 95 mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); 96 mAlertParams.mNegativeButtonListener = this; 97 mAlertParams.mView = view; 98 setupAlert(); 99 100 if (mHandler == null) { 101 mHandler = new Handler(this); 102 } 103 mHandler.sendEmptyMessage(0); 104 } catch (Exception e) { 105 Log.e(TAG, "onResume", e); 106 finish(); 107 } 108 } 109 110 @Override onPause()111 protected void onPause() { 112 super.onPause(); 113 if (!isFinishing()) { 114 finish(); 115 } 116 } 117 118 @Override onClick(DialogInterface dialog, int which)119 public void onClick(DialogInterface dialog, int which) { 120 try { 121 if (which == DialogInterface.BUTTON_POSITIVE) { 122 mConfig.configureIntent.send(); 123 } else if (which == DialogInterface.BUTTON_NEUTRAL) { 124 final int myUserId = UserHandle.myUserId(); 125 if (mConfig.legacy) { 126 mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN, myUserId); 127 } else { 128 mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN, myUserId); 129 } 130 } 131 } catch (Exception e) { 132 Log.e(TAG, "onClick", e); 133 finish(); 134 } 135 } 136 137 @Override handleMessage(Message message)138 public boolean handleMessage(Message message) { 139 mHandler.removeMessages(0); 140 141 if (!isFinishing()) { 142 if (mConfig.startTime != -1) { 143 long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000; 144 mDuration.setText(String.format("%02d:%02d:%02d", 145 seconds / 3600, seconds / 60 % 60, seconds % 60)); 146 } 147 148 String[] numbers = getNumbers(); 149 if (numbers != null) { 150 // First unhide the related data rows. 151 if (mDataRowsHidden) { 152 findViewById(R.id.data_transmitted_row).setVisibility(View.VISIBLE); 153 findViewById(R.id.data_received_row).setVisibility(View.VISIBLE); 154 mDataRowsHidden = false; 155 } 156 157 // [1] and [2] are received data in bytes and packets. 158 mDataReceived.setText(getString(R.string.data_value_format, 159 numbers[1], numbers[2])); 160 161 // [9] and [10] are transmitted data in bytes and packets. 162 mDataTransmitted.setText(getString(R.string.data_value_format, 163 numbers[9], numbers[10])); 164 } 165 mHandler.sendEmptyMessageDelayed(0, 1000); 166 } 167 return true; 168 } 169 getNumbers()170 private String[] getNumbers() { 171 DataInputStream in = null; 172 try { 173 // See dev_seq_printf_stats() in net/core/dev.c. 174 in = new DataInputStream(new FileInputStream("/proc/net/dev")); 175 String prefix = mConfig.interfaze + ':'; 176 177 while (true) { 178 String line = in.readLine().trim(); 179 if (line.startsWith(prefix)) { 180 String[] numbers = line.substring(prefix.length()).split(" +"); 181 for (int i = 1; i < 17; ++i) { 182 if (!numbers[i].equals("0")) { 183 return numbers; 184 } 185 } 186 break; 187 } 188 } 189 } catch (Exception e) { 190 // ignore 191 } finally { 192 try { 193 in.close(); 194 } catch (Exception e) { 195 // ignore 196 } 197 } 198 return null; 199 } 200 } 201