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