diff options
Diffstat (limited to 'telephony/java/com/android/internal/telephony/gsm/PppLink.java')
-rw-r--r-- | telephony/java/com/android/internal/telephony/gsm/PppLink.java | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/telephony/java/com/android/internal/telephony/gsm/PppLink.java b/telephony/java/com/android/internal/telephony/gsm/PppLink.java new file mode 100644 index 0000000..43d4f1f --- /dev/null +++ b/telephony/java/com/android/internal/telephony/gsm/PppLink.java @@ -0,0 +1,209 @@ +/* + * 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); + } + } + } + + } +} |