| /* |
| * Copyright (C) 2006 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.internal.telephony.gsm; |
| |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.RandomAccessFile; |
| |
| import android.database.Cursor; |
| import android.os.Message; |
| import android.os.SystemProperties; |
| import android.os.SystemService; |
| import com.android.internal.telephony.gsm.DataConnectionTracker.State; |
| import com.android.internal.util.ArrayUtils; |
| import android.util.Log; |
| |
| /** |
| * Represents a PPP link. |
| * |
| * Ideally this would be managed by the RIL implementation, but |
| * we currently have implementations where this is not the case. |
| * |
| * {@hide} |
| */ |
| final class PppLink extends DataLink implements DataLinkInterface { |
| private static final String LOG_TAG = "GSM"; |
| |
| static final String PATH_PPP_OPERSTATE = "/sys/class/net/ppp0/operstate"; |
| static final String SERVICE_PPPD_GPRS = "pppd_gprs"; |
| static final String PROPERTY_PPPD_EXIT_CODE = "net.gprs.ppp-exit"; |
| static final int POLL_SYSFS_MILLIS = 5 * 1000; |
| static final int EVENT_POLL_DATA_CONNECTION = 2; |
| static final int EVENT_PPP_OPERSTATE_CHANGED = 8; |
| static final int EVENT_PPP_PIDFILE_CHANGED = 9; |
| |
| static final byte[] UP_ASCII_STRING = new byte[] { |
| 'u' & 0xff, |
| 'p' & 0xff, |
| }; |
| static final byte[] DOWN_ASCII_STRING = new byte[] { |
| 'd' & 0xff, |
| 'o' & 0xff, |
| 'w' & 0xff, |
| 'n' & 0xff, |
| }; |
| static final byte[] UNKNOWN_ASCII_STRING = new byte[] { |
| 'u' & 0xff, |
| 'n' & 0xff, |
| 'k' & 0xff, |
| 'n' & 0xff, |
| 'o' & 0xff, |
| 'w' & 0xff, |
| 'n' & 0xff, |
| }; |
| private final byte[] mCheckPPPBuffer = new byte[32]; |
| |
| int lastPppdExitCode = EXIT_OK; |
| |
| |
| PppLink(DataConnectionTracker dc) { |
| super(dc); |
| } |
| |
| public void connect() { |
| // Clear any previous exit code |
| SystemProperties.set(PROPERTY_PPPD_EXIT_CODE, ""); |
| SystemService.start(SERVICE_PPPD_GPRS); |
| removeMessages(EVENT_POLL_DATA_CONNECTION); |
| Message poll = obtainMessage(); |
| poll.what = EVENT_POLL_DATA_CONNECTION; |
| sendMessageDelayed(poll, POLL_SYSFS_MILLIS); |
| } |
| |
| public void disconnect() { |
| SystemService.stop(SERVICE_PPPD_GPRS); |
| } |
| |
| public int getLastLinkExitCode() { |
| return lastPppdExitCode; |
| } |
| |
| public void setPasswordInfo(Cursor cursor) { |
| StringBuilder builder = new StringBuilder(); |
| FileOutputStream output = null; |
| |
| try { |
| output = new FileOutputStream("/etc/ppp/pap-secrets"); |
| if (cursor.moveToFirst()) { |
| do { |
| builder.append(cursor.getString(cursor.getColumnIndex("user"))); |
| builder.append(" "); |
| builder.append(cursor.getString(cursor.getColumnIndex("server"))); |
| builder.append(" "); |
| builder.append(cursor.getString(cursor.getColumnIndex("password"))); |
| builder.append("\n"); |
| } while (cursor.moveToNext()); |
| } |
| |
| output.write(builder.toString().getBytes()); |
| } catch (java.io.IOException e) { |
| Log.e(LOG_TAG, "Could not create '/etc/ppp/pap-secrets'", e); |
| } finally { |
| try { |
| if (output != null) output.close(); |
| } catch (java.io.IOException e) { |
| Log.e(LOG_TAG, "Error closing '/etc/ppp/pap-secrets'", e); |
| } |
| } |
| } |
| |
| public void handleMessage (Message msg) { |
| |
| switch (msg.what) { |
| |
| case EVENT_POLL_DATA_CONNECTION: |
| checkPPP(); |
| |
| // keep polling in case interface goes down |
| if (dataConnection.state != State.IDLE) { |
| Message poll = obtainMessage(); |
| poll.what = EVENT_POLL_DATA_CONNECTION; |
| sendMessageDelayed(poll, POLL_SYSFS_MILLIS); |
| } |
| break; |
| } |
| } |
| |
| private void checkPPP() { |
| boolean connecting = (dataConnection.state == State.CONNECTING); |
| |
| try { |
| RandomAccessFile file = new RandomAccessFile(PATH_PPP_OPERSTATE, "r"); |
| file.read(mCheckPPPBuffer); |
| file.close(); |
| |
| // Unfortunately, we're currently seeing operstate |
| // "unknown" where one might otherwise expect "up" |
| if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length) |
| || ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING, |
| UNKNOWN_ASCII_STRING.length) |
| && dataConnection.state == State.CONNECTING) { |
| |
| Log.i(LOG_TAG, |
| "found ppp interface. Notifying GPRS connected"); |
| |
| if (mLinkChangeRegistrant != null) { |
| mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP); |
| } |
| |
| connecting = false; |
| } else if (dataConnection.state == State.CONNECTED |
| && ArrayUtils.equals(mCheckPPPBuffer, DOWN_ASCII_STRING, |
| DOWN_ASCII_STRING.length)) { |
| |
| Log.i(LOG_TAG, |
| "ppp interface went down. Reconnecting..."); |
| |
| if (mLinkChangeRegistrant != null) { |
| mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN); |
| } |
| } |
| } catch (IOException ex) { |
| if (! (ex instanceof FileNotFoundException)) { |
| Log.i(LOG_TAG, "Poll ppp0 ex " + ex.toString()); |
| } |
| |
| if (dataConnection.state == State.CONNECTED && |
| mLinkChangeRegistrant != null) { |
| mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN); |
| } |
| } |
| |
| // CONNECTING means pppd has started but negotiation is not complete |
| // If we're still CONNECTING here, check to see if pppd has |
| // already exited |
| if (connecting) { |
| String exitCode; |
| |
| exitCode = SystemProperties.get(PROPERTY_PPPD_EXIT_CODE, ""); |
| |
| if (!exitCode.equals("")) { |
| // pppd has exited. Let's figure out why |
| lastPppdExitCode = Integer.parseInt(exitCode); |
| |
| Log.d(LOG_TAG,"pppd exited with " + exitCode); |
| |
| if (mLinkChangeRegistrant != null) { |
| mLinkChangeRegistrant.notifyResult(LinkState.LINK_EXITED); |
| } |
| } |
| } |
| |
| } |
| } |