Loading core/java/com/android/internal/net/LegacyVpnInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class LegacyVpnInfo implements Parcelable { public String key; public int state = -1; public PendingIntent intent; @Override public int describeContents() { Loading @@ -50,6 +51,7 @@ public class LegacyVpnInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(key); out.writeInt(state); out.writeParcelable(intent, flags); } public static final Parcelable.Creator<LegacyVpnInfo> CREATOR = Loading @@ -59,6 +61,7 @@ public class LegacyVpnInfo implements Parcelable { LegacyVpnInfo info = new LegacyVpnInfo(); info.key = in.readString(); info.state = in.readInt(); info.intent = in.readParcelable(null); return info; } Loading core/java/com/android/internal/net/VpnConfig.java +10 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.net.LinkAddress; import android.net.RouteInfo; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import java.net.Inet4Address; import java.net.InetAddress; Loading Loading @@ -57,6 +58,15 @@ public class VpnConfig implements Parcelable { return intent; } /** NOTE: This should only be used for legacy VPN. */ public static PendingIntent getIntentForStatusPanel(Context context) { Intent intent = new Intent(); intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT); } public static CharSequence getVpnLabel(Context context, String packageName) throws NameNotFoundException { PackageManager pm = context.getPackageManager(); Loading packages/VpnDialogs/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -28,5 +28,14 @@ <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".ManageDialog" android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> </application> </manifest> packages/VpnDialogs/res/layout/manage.xml 0 → 100644 +46 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2011 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="3mm" android:stretchColumns="0,1" android:shrinkColumns="1"> <TableRow> <TextView android:text="@string/session" style="@style/label"/> <TextView android:id="@+id/session" style="@style/value"/> </TableRow> <TableRow> <TextView android:text="@string/duration" style="@style/label"/> <TextView android:id="@+id/duration" style="@style/value"/> </TableRow> <TableRow android:id="@+id/data_transmitted_row" android:visibility="gone"> <TextView android:text="@string/data_transmitted" style="@style/label"/> <TextView android:id="@+id/data_transmitted" style="@style/value"/> </TableRow> <TableRow android:id="@+id/data_received_row" android:visibility="gone"> <TextView android:text="@string/data_received" style="@style/label"/> <TextView android:id="@+id/data_received" style="@style/value"/> </TableRow> </TableLayout> packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java 0 → 100644 +198 −0 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.vpndialogs; import android.content.Context; import android.content.DialogInterface; import android.net.IConnectivityManager; import android.os.Handler; import android.os.Message; import android.os.ServiceManager; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.widget.TextView; import com.android.internal.app.AlertActivity; import com.android.internal.net.VpnConfig; import java.io.DataInputStream; import java.io.FileInputStream; public class ManageDialog extends AlertActivity implements DialogInterface.OnClickListener, Handler.Callback { private static final String TAG = "VpnManage"; private VpnConfig mConfig; private IConnectivityManager mService; private TextView mDuration; private TextView mDataTransmitted; private TextView mDataReceived; private boolean mDataRowsHidden; private Handler mHandler; @Override protected void onResume() { super.onResume(); if (getCallingPackage() != null) { Log.e(TAG, getCallingPackage() + " cannot start this activity"); finish(); return; } try { mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); mConfig = mService.getVpnConfig(); // mConfig can be null if we are a restricted user, in that case don't show this dialog if (mConfig == null) { finish(); return; } View view = View.inflate(this, R.layout.manage, null); if (mConfig.session != null) { ((TextView) view.findViewById(R.id.session)).setText(mConfig.session); } mDuration = (TextView) view.findViewById(R.id.duration); mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted); mDataReceived = (TextView) view.findViewById(R.id.data_received); mDataRowsHidden = true; if (mConfig.legacy) { mAlertParams.mTitle = getText(R.string.legacy_title); } else { mAlertParams.mTitle = VpnConfig.getVpnLabel(this, mConfig.user); } if (mConfig.configureIntent != null) { mAlertParams.mPositiveButtonText = getText(R.string.configure); mAlertParams.mPositiveButtonListener = this; } mAlertParams.mNeutralButtonText = getText(R.string.disconnect); mAlertParams.mNeutralButtonListener = this; mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); mAlertParams.mNegativeButtonListener = this; mAlertParams.mView = view; setupAlert(); if (mHandler == null) { mHandler = new Handler(this); } mHandler.sendEmptyMessage(0); } catch (Exception e) { Log.e(TAG, "onResume", e); finish(); } } @Override protected void onPause() { super.onPause(); if (!isFinishing()) { finish(); } } @Override public void onClick(DialogInterface dialog, int which) { try { if (which == DialogInterface.BUTTON_POSITIVE) { mConfig.configureIntent.send(); } else if (which == DialogInterface.BUTTON_NEUTRAL) { if (mConfig.legacy) { mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); } else { mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); } } } catch (Exception e) { Log.e(TAG, "onClick", e); finish(); } } @Override public boolean handleMessage(Message message) { mHandler.removeMessages(0); if (!isFinishing()) { if (mConfig.startTime != -1) { long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000; mDuration.setText(String.format("%02d:%02d:%02d", seconds / 3600, seconds / 60 % 60, seconds % 60)); } String[] numbers = getNumbers(); if (numbers != null) { // First unhide the related data rows. if (mDataRowsHidden) { findViewById(R.id.data_transmitted_row).setVisibility(View.VISIBLE); findViewById(R.id.data_received_row).setVisibility(View.VISIBLE); mDataRowsHidden = false; } // [1] and [2] are received data in bytes and packets. mDataReceived.setText(getString(R.string.data_value_format, numbers[1], numbers[2])); // [9] and [10] are transmitted data in bytes and packets. mDataTransmitted.setText(getString(R.string.data_value_format, numbers[9], numbers[10])); } mHandler.sendEmptyMessageDelayed(0, 1000); } return true; } private String[] getNumbers() { DataInputStream in = null; try { // See dev_seq_printf_stats() in net/core/dev.c. in = new DataInputStream(new FileInputStream("/proc/net/dev")); String prefix = mConfig.interfaze + ':'; while (true) { String line = in.readLine().trim(); if (line.startsWith(prefix)) { String[] numbers = line.substring(prefix.length()).split(" +"); for (int i = 1; i < 17; ++i) { if (!numbers[i].equals("0")) { return numbers; } } break; } } } catch (Exception e) { // ignore } finally { try { in.close(); } catch (Exception e) { // ignore } } return null; } } Loading
core/java/com/android/internal/net/LegacyVpnInfo.java +3 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class LegacyVpnInfo implements Parcelable { public String key; public int state = -1; public PendingIntent intent; @Override public int describeContents() { Loading @@ -50,6 +51,7 @@ public class LegacyVpnInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(key); out.writeInt(state); out.writeParcelable(intent, flags); } public static final Parcelable.Creator<LegacyVpnInfo> CREATOR = Loading @@ -59,6 +61,7 @@ public class LegacyVpnInfo implements Parcelable { LegacyVpnInfo info = new LegacyVpnInfo(); info.key = in.readString(); info.state = in.readInt(); info.intent = in.readParcelable(null); return info; } Loading
core/java/com/android/internal/net/VpnConfig.java +10 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.net.LinkAddress; import android.net.RouteInfo; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import java.net.Inet4Address; import java.net.InetAddress; Loading Loading @@ -57,6 +58,15 @@ public class VpnConfig implements Parcelable { return intent; } /** NOTE: This should only be used for legacy VPN. */ public static PendingIntent getIntentForStatusPanel(Context context) { Intent intent = new Intent(); intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT); } public static CharSequence getVpnLabel(Context context, String packageName) throws NameNotFoundException { PackageManager pm = context.getPackageManager(); Loading
packages/VpnDialogs/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -28,5 +28,14 @@ <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".ManageDialog" android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" android:noHistory="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> </application> </manifest>
packages/VpnDialogs/res/layout/manage.xml 0 → 100644 +46 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2011 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="3mm" android:stretchColumns="0,1" android:shrinkColumns="1"> <TableRow> <TextView android:text="@string/session" style="@style/label"/> <TextView android:id="@+id/session" style="@style/value"/> </TableRow> <TableRow> <TextView android:text="@string/duration" style="@style/label"/> <TextView android:id="@+id/duration" style="@style/value"/> </TableRow> <TableRow android:id="@+id/data_transmitted_row" android:visibility="gone"> <TextView android:text="@string/data_transmitted" style="@style/label"/> <TextView android:id="@+id/data_transmitted" style="@style/value"/> </TableRow> <TableRow android:id="@+id/data_received_row" android:visibility="gone"> <TextView android:text="@string/data_received" style="@style/label"/> <TextView android:id="@+id/data_received" style="@style/value"/> </TableRow> </TableLayout>
packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java 0 → 100644 +198 −0 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.vpndialogs; import android.content.Context; import android.content.DialogInterface; import android.net.IConnectivityManager; import android.os.Handler; import android.os.Message; import android.os.ServiceManager; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.widget.TextView; import com.android.internal.app.AlertActivity; import com.android.internal.net.VpnConfig; import java.io.DataInputStream; import java.io.FileInputStream; public class ManageDialog extends AlertActivity implements DialogInterface.OnClickListener, Handler.Callback { private static final String TAG = "VpnManage"; private VpnConfig mConfig; private IConnectivityManager mService; private TextView mDuration; private TextView mDataTransmitted; private TextView mDataReceived; private boolean mDataRowsHidden; private Handler mHandler; @Override protected void onResume() { super.onResume(); if (getCallingPackage() != null) { Log.e(TAG, getCallingPackage() + " cannot start this activity"); finish(); return; } try { mService = IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); mConfig = mService.getVpnConfig(); // mConfig can be null if we are a restricted user, in that case don't show this dialog if (mConfig == null) { finish(); return; } View view = View.inflate(this, R.layout.manage, null); if (mConfig.session != null) { ((TextView) view.findViewById(R.id.session)).setText(mConfig.session); } mDuration = (TextView) view.findViewById(R.id.duration); mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted); mDataReceived = (TextView) view.findViewById(R.id.data_received); mDataRowsHidden = true; if (mConfig.legacy) { mAlertParams.mTitle = getText(R.string.legacy_title); } else { mAlertParams.mTitle = VpnConfig.getVpnLabel(this, mConfig.user); } if (mConfig.configureIntent != null) { mAlertParams.mPositiveButtonText = getText(R.string.configure); mAlertParams.mPositiveButtonListener = this; } mAlertParams.mNeutralButtonText = getText(R.string.disconnect); mAlertParams.mNeutralButtonListener = this; mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); mAlertParams.mNegativeButtonListener = this; mAlertParams.mView = view; setupAlert(); if (mHandler == null) { mHandler = new Handler(this); } mHandler.sendEmptyMessage(0); } catch (Exception e) { Log.e(TAG, "onResume", e); finish(); } } @Override protected void onPause() { super.onPause(); if (!isFinishing()) { finish(); } } @Override public void onClick(DialogInterface dialog, int which) { try { if (which == DialogInterface.BUTTON_POSITIVE) { mConfig.configureIntent.send(); } else if (which == DialogInterface.BUTTON_NEUTRAL) { if (mConfig.legacy) { mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); } else { mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN); } } } catch (Exception e) { Log.e(TAG, "onClick", e); finish(); } } @Override public boolean handleMessage(Message message) { mHandler.removeMessages(0); if (!isFinishing()) { if (mConfig.startTime != -1) { long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000; mDuration.setText(String.format("%02d:%02d:%02d", seconds / 3600, seconds / 60 % 60, seconds % 60)); } String[] numbers = getNumbers(); if (numbers != null) { // First unhide the related data rows. if (mDataRowsHidden) { findViewById(R.id.data_transmitted_row).setVisibility(View.VISIBLE); findViewById(R.id.data_received_row).setVisibility(View.VISIBLE); mDataRowsHidden = false; } // [1] and [2] are received data in bytes and packets. mDataReceived.setText(getString(R.string.data_value_format, numbers[1], numbers[2])); // [9] and [10] are transmitted data in bytes and packets. mDataTransmitted.setText(getString(R.string.data_value_format, numbers[9], numbers[10])); } mHandler.sendEmptyMessageDelayed(0, 1000); } return true; } private String[] getNumbers() { DataInputStream in = null; try { // See dev_seq_printf_stats() in net/core/dev.c. in = new DataInputStream(new FileInputStream("/proc/net/dev")); String prefix = mConfig.interfaze + ':'; while (true) { String line = in.readLine().trim(); if (line.startsWith(prefix)) { String[] numbers = line.substring(prefix.length()).split(" +"); for (int i = 1; i < 17; ++i) { if (!numbers[i].equals("0")) { return numbers; } } break; } } } catch (Exception e) { // ignore } finally { try { in.close(); } catch (Exception e) { // ignore } } return null; } }