1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.terminal; 18 19 import android.graphics.Color; 20 21 /** 22 * Single terminal session backed by a pseudo terminal on the local device. 23 */ 24 public class Terminal { 25 public static final String TAG = "Terminal"; 26 27 public final int key; 28 29 private static int sNumber = 0; 30 31 static { 32 System.loadLibrary("jni_terminal"); 33 } 34 35 /** 36 * Represents a run of one or more {@code VTermScreenCell} which all have 37 * the same formatting. 38 */ 39 public static class CellRun { 40 char[] data; 41 int dataSize; 42 int colSize; 43 44 boolean bold; 45 int underline; 46 boolean blink; 47 boolean reverse; 48 boolean strike; 49 int font; 50 51 int fg = Color.CYAN; 52 int bg = Color.DKGRAY; 53 } 54 55 // NOTE: clients must not call back into terminal while handling a callback, 56 // since native mutex isn't reentrant. 57 public interface TerminalClient { onDamage(int startRow, int endRow, int startCol, int endCol)58 public void onDamage(int startRow, int endRow, int startCol, int endCol); onMoveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol)59 public void onMoveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, 60 int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol); onMoveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible)61 public void onMoveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible); onBell()62 public void onBell(); 63 } 64 65 private final long mNativePtr; 66 private final Thread mThread; 67 68 private String mTitle; 69 70 private TerminalClient mClient; 71 72 private boolean mCursorVisible; 73 private int mCursorRow; 74 private int mCursorCol; 75 76 private final TerminalCallbacks mCallbacks = new TerminalCallbacks() { 77 @Override 78 public int damage(int startRow, int endRow, int startCol, int endCol) { 79 if (mClient != null) { 80 mClient.onDamage(startRow, endRow, startCol, endCol); 81 } 82 return 1; 83 } 84 85 @Override 86 public int moveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, 87 int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol) { 88 if (mClient != null) { 89 mClient.onMoveRect(destStartRow, destEndRow, destStartCol, destEndCol, srcStartRow, 90 srcEndRow, srcStartCol, srcEndCol); 91 } 92 return 1; 93 } 94 95 @Override 96 public int moveCursor(int posRow, int posCol, int oldPosRow, int oldPosCol, int visible) { 97 mCursorVisible = (visible != 0); 98 mCursorRow = posRow; 99 mCursorCol = posCol; 100 if (mClient != null) { 101 mClient.onMoveCursor(posRow, posCol, oldPosRow, oldPosCol, visible); 102 } 103 return 1; 104 } 105 106 @Override 107 public int bell() { 108 if (mClient != null) { 109 mClient.onBell(); 110 } 111 return 1; 112 } 113 }; 114 Terminal()115 public Terminal() { 116 mNativePtr = nativeInit(mCallbacks); 117 key = sNumber++; 118 mTitle = TAG + " " + key; 119 mThread = new Thread(mTitle) { 120 @Override 121 public void run() { 122 nativeRun(mNativePtr); 123 } 124 }; 125 } 126 127 /** 128 * Start thread which internally forks and manages the pseudo terminal. 129 */ start()130 public void start() { 131 mThread.start(); 132 } 133 destroy()134 public void destroy() { 135 if (nativeDestroy(mNativePtr) != 0) { 136 throw new IllegalStateException("destroy failed"); 137 } 138 } 139 setClient(TerminalClient client)140 public void setClient(TerminalClient client) { 141 mClient = client; 142 } 143 resize(int rows, int cols, int scrollRows)144 public void resize(int rows, int cols, int scrollRows) { 145 if (nativeResize(mNativePtr, rows, cols, scrollRows) != 0) { 146 throw new IllegalStateException("resize failed"); 147 } 148 } 149 getRows()150 public int getRows() { 151 return nativeGetRows(mNativePtr); 152 } 153 getCols()154 public int getCols() { 155 return nativeGetCols(mNativePtr); 156 } 157 getScrollRows()158 public int getScrollRows() { 159 return nativeGetScrollRows(mNativePtr); 160 } 161 getCellRun(int row, int col, CellRun run)162 public void getCellRun(int row, int col, CellRun run) { 163 if (nativeGetCellRun(mNativePtr, row, col, run) != 0) { 164 throw new IllegalStateException("getCell failed"); 165 } 166 } 167 getCursorVisible()168 public boolean getCursorVisible() { 169 return mCursorVisible; 170 } 171 getCursorRow()172 public int getCursorRow() { 173 return mCursorRow; 174 } 175 getCursorCol()176 public int getCursorCol() { 177 return mCursorCol; 178 } 179 getTitle()180 public String getTitle() { 181 // TODO: hook up to title passed through termprop 182 return mTitle; 183 } 184 dispatchKey(int modifiers, int key)185 public boolean dispatchKey(int modifiers, int key) { 186 return nativeDispatchKey(mNativePtr, modifiers, key); 187 } 188 dispatchCharacter(int modifiers, int character)189 public boolean dispatchCharacter(int modifiers, int character) { 190 return nativeDispatchCharacter(mNativePtr, modifiers, character); 191 } 192 nativeInit(TerminalCallbacks callbacks)193 private static native long nativeInit(TerminalCallbacks callbacks); nativeDestroy(long ptr)194 private static native int nativeDestroy(long ptr); 195 nativeRun(long ptr)196 private static native int nativeRun(long ptr); nativeResize(long ptr, int rows, int cols, int scrollRows)197 private static native int nativeResize(long ptr, int rows, int cols, int scrollRows); nativeGetCellRun(long ptr, int row, int col, CellRun run)198 private static native int nativeGetCellRun(long ptr, int row, int col, CellRun run); nativeGetRows(long ptr)199 private static native int nativeGetRows(long ptr); nativeGetCols(long ptr)200 private static native int nativeGetCols(long ptr); nativeGetScrollRows(long ptr)201 private static native int nativeGetScrollRows(long ptr); 202 nativeDispatchKey(long ptr, int modifiers, int key)203 private static native boolean nativeDispatchKey(long ptr, int modifiers, int key); nativeDispatchCharacter(long ptr, int modifiers, int character)204 private static native boolean nativeDispatchCharacter(long ptr, int modifiers, int character); 205 } 206