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