119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh/*
219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * Copyright (C) 2011 The Android Open Source Project
319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh *
419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * you may not use this file except in compliance with the License.
619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * You may obtain a copy of the License at
719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh *
819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh *
1019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * See the License for the specific language governing permissions and
1419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh * limitations under the License.
1519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh */
1619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
1719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehpackage com.android.vpndialogs;
1819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
1919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.app.Activity;
2019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.app.AlertDialog;
2119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.content.Context;
2219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.content.DialogInterface;
2319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.content.Intent;
2419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.content.pm.ApplicationInfo;
2519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.content.pm.PackageManager;
26f530da67b4f9ffa55bb8a1c05390c6f7f87fe4baChia-chi Yehimport android.net.IConnectivityManager;
2719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.os.Handler;
2819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.os.Message;
29f530da67b4f9ffa55bb8a1c05390c6f7f87fe4baChia-chi Yehimport android.os.ServiceManager;
3019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.os.SystemClock;
3119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.util.Log;
3219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.view.View;
3319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.widget.Button;
3419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.widget.CompoundButton;
3519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.widget.ImageView;
3619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport android.widget.TextView;
3719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
3842bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yehimport com.android.internal.net.VpnConfig;
3942bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh
4019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport java.io.DataInputStream;
4119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yehimport java.io.FileInputStream;
4219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
4342bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yehpublic class ManageDialog extends Activity implements Handler.Callback,
4419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
4519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private static final String TAG = "VpnManage";
4619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
4742bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh    private VpnConfig mConfig;
4819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
49f530da67b4f9ffa55bb8a1c05390c6f7f87fe4baChia-chi Yeh    private IConnectivityManager mService;
5019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
5119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private AlertDialog mDialog;
5219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private TextView mDuration;
5319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private TextView mDataTransmitted;
5419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private TextView mDataReceived;
5519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
5642bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh    private Handler mHandler;
5719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
5819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    @Override
5919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    protected void onResume() {
6019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        super.onResume();
61339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh
62339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh        if (getCallingPackage() != null) {
63339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh            Log.e(TAG, getCallingPackage() + " cannot start this activity");
64339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh            finish();
65339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh            return;
66339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh        }
67339abf1fbac25321cea9d39de14b6a6b4e326120Chia-chi Yeh
6819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        try {
6942bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            mConfig = getIntent().getParcelableExtra("config");
7019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
71f530da67b4f9ffa55bb8a1c05390c6f7f87fe4baChia-chi Yeh            mService = IConnectivityManager.Stub.asInterface(
72f530da67b4f9ffa55bb8a1c05390c6f7f87fe4baChia-chi Yeh                    ServiceManager.getService(Context.CONNECTIVITY_SERVICE));
7319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
7419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            View view = View.inflate(this, R.layout.manage, null);
7534e7813e962de99df9813014678ef5901227c5f1Chia-chi Yeh            if (mConfig.session != null) {
7634e7813e962de99df9813014678ef5901227c5f1Chia-chi Yeh                ((TextView) view.findViewById(R.id.session)).setText(mConfig.session);
7719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            }
7819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDuration = (TextView) view.findViewById(R.id.duration);
7919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
8019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDataReceived = (TextView) view.findViewById(R.id.data_received);
8119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
82fcc1b41b663c1a0cb551344c4a16a5ad9ce36d60Chia-chi Yeh            if (mConfig.user.equals(VpnConfig.LEGACY_VPN)) {
835db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                mDialog = new AlertDialog.Builder(this)
845db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setIcon(android.R.drawable.ic_dialog_info)
855db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setTitle(R.string.legacy_title)
865db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setView(view)
875db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setNeutralButton(R.string.disconnect, this)
885db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setNegativeButton(android.R.string.cancel, this)
895db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .create();
905db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh            } else {
915db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                PackageManager pm = getPackageManager();
92fcc1b41b663c1a0cb551344c4a16a5ad9ce36d60Chia-chi Yeh                ApplicationInfo app = pm.getApplicationInfo(mConfig.user, 0);
935db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                mDialog = new AlertDialog.Builder(this)
945db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setIcon(app.loadIcon(pm))
955db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setTitle(app.loadLabel(pm))
965db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setView(view)
975db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setNeutralButton(R.string.disconnect, this)
985db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .setNegativeButton(android.R.string.cancel, this)
995db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                        .create();
1005db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh            }
10142bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh
1025db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh            if (mConfig.configureIntent != null) {
10342bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                mDialog.setButton(DialogInterface.BUTTON_POSITIVE,
10442bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                        getText(R.string.configure), this);
10542bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            }
10619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDialog.setOnDismissListener(this);
10719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDialog.show();
10819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
10942bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            if (mHandler == null) {
11042bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                mHandler = new Handler(this);
11142bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            }
11242bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            mHandler.sendEmptyMessage(0);
11319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        } catch (Exception e) {
11419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            Log.e(TAG, "onResume", e);
11519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            finish();
11619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        }
11719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
11819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
11919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    @Override
12019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    protected void onPause() {
12119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        super.onPause();
12219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        if (mDialog != null) {
12319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDialog.setOnDismissListener(null);
12419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            mDialog.dismiss();
12519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        }
12619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
12719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
12819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    @Override
12919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    public void onClick(DialogInterface dialog, int which) {
13019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        try {
13119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            if (which == AlertDialog.BUTTON_POSITIVE) {
1325db03df1fff4900eb485304d4fd185110bea1a0cChia-chi Yeh                mConfig.configureIntent.send();
13319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            } else if (which == AlertDialog.BUTTON_NEUTRAL) {
134fcc1b41b663c1a0cb551344c4a16a5ad9ce36d60Chia-chi Yeh                mService.prepareVpn(mConfig.user, VpnConfig.LEGACY_VPN);
13519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            }
13619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        } catch (Exception e) {
13719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            Log.e(TAG, "onClick", e);
13842bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            finish();
13919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        }
14019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
14119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
14219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    @Override
14319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    public void onDismiss(DialogInterface dialog) {
14419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        finish();
14519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
14619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
14742bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh    @Override
14842bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh    public boolean handleMessage(Message message) {
14942bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh        mHandler.removeMessages(0);
15042bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh
15142bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh        if (mDialog.isShowing()) {
15242bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            if (mConfig.startTime != 0) {
15342bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                long seconds = (SystemClock.elapsedRealtime() - mConfig.startTime) / 1000;
15442bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                mDuration.setText(String.format("%02d:%02d:%02d",
15542bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                        seconds / 3600, seconds / 60 % 60, seconds % 60));
15642bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            }
15719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
15842bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            String[] numbers = getStatistics();
15942bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            if (numbers != null) {
16042bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                // [1] and [2] are received data in bytes and packets.
16142bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                mDataReceived.setText(getString(R.string.data_value_format,
16242bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                        numbers[1], numbers[2]));
16319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
16442bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                // [9] and [10] are transmitted data in bytes and packets.
16542bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                mDataTransmitted.setText(getString(R.string.data_value_format,
16642bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh                        numbers[9], numbers[10]));
16719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            }
16842bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh            mHandler.sendEmptyMessageDelayed(0, 1000);
16919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        }
17042bd53a9ff3f6358485e37df970754833aab2629Chia-chi Yeh        return true;
17119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
17219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
17319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    private String[] getStatistics() {
17419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        DataInputStream in = null;
17519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        try {
17619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            // See dev_seq_printf_stats() in net/core/dev.c.
17719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            in = new DataInputStream(new FileInputStream("/proc/net/dev"));
17834e7813e962de99df9813014678ef5901227c5f1Chia-chi Yeh            String prefix = mConfig.interfaze + ':';
17919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh
18019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            while (true) {
18119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                String line = in.readLine().trim();
18219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                if (line.startsWith(prefix)) {
18319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                    String[] numbers = line.substring(prefix.length()).split(" +");
18472fddaa5d9b295571b63ec6bc28dcdd9eda482b1Chia-chi Yeh                    for (int i = 1; i < 17; ++i) {
18572fddaa5d9b295571b63ec6bc28dcdd9eda482b1Chia-chi Yeh                        if (!numbers[i].equals("0")) {
18672fddaa5d9b295571b63ec6bc28dcdd9eda482b1Chia-chi Yeh                            return numbers;
18772fddaa5d9b295571b63ec6bc28dcdd9eda482b1Chia-chi Yeh                        }
18819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                    }
18919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                    break;
19019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                }
19119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            }
19219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        } catch (Exception e) {
19319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            // ignore
19419f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        } finally {
19519f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            try {
19619f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                in.close();
19719f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            } catch (Exception e) {
19819f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh                // ignore
19919f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh            }
20019f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        }
20119f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh        return null;
20219f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh    }
20319f054b0f69b2f56ea0e98a3bb7e0e62b90ff480Chia-chi Yeh}
204