summaryrefslogtreecommitdiffstats
path: root/telephony/java/com/android/internal/telephony/gsm/PppLink.java
diff options
context:
space:
mode:
Diffstat (limited to 'telephony/java/com/android/internal/telephony/gsm/PppLink.java')
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/PppLink.java209
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);
+ }
+ }
+ }
+
+ }
+}