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); onBell()61 public void onBell(); 62 } 63 64 private final long mNativePtr; 65 private final Thread mThread; 66 67 private String mTitle; 68 69 private TerminalClient mClient; 70 71 private final TerminalCallbacks mCallbacks = new TerminalCallbacks() { 72 @Override 73 public int damage(int startRow, int endRow, int startCol, int endCol) { 74 if (mClient != null) { 75 mClient.onDamage(startRow, endRow, startCol, endCol); 76 } 77 return 1; 78 } 79 80 @Override 81 public int moveRect(int destStartRow, int destEndRow, int destStartCol, int destEndCol, 82 int srcStartRow, int srcEndRow, int srcStartCol, int srcEndCol) { 83 if (mClient != null) { 84 mClient.onMoveRect(destStartRow, destEndRow, destStartCol, destEndCol, srcStartRow, 85 srcEndRow, srcStartCol, srcEndCol); 86 } 87 return 1; 88 } 89 90 @Override 91 public int bell() { 92 if (mClient != null) { 93 mClient.onBell(); 94 } 95 return 1; 96 } 97 }; 98 Terminal()99 public Terminal() { 100 mNativePtr = nativeInit(mCallbacks, 25, 80); 101 key = sNumber++; 102 mTitle = TAG + " " + key; 103 mThread = new Thread(mTitle) { 104 @Override 105 public void run() { 106 nativeRun(mNativePtr); 107 } 108 }; 109 } 110 111 /** 112 * Start thread which internally forks and manages the pseudo terminal. 113 */ start()114 public void start() { 115 mThread.start(); 116 } 117 destroy()118 public void destroy() { 119 if (nativeDestroy(mNativePtr) != 0) { 120 throw new IllegalStateException("destroy failed"); 121 } 122 } 123 setClient(TerminalClient client)124 public void setClient(TerminalClient client) { 125 mClient = client; 126 } 127 resize(int rows, int cols, int scrollRows)128 public void resize(int rows, int cols, int scrollRows) { 129 if (nativeResize(mNativePtr, rows, cols, scrollRows) != 0) { 130 throw new IllegalStateException("resize failed"); 131 } 132 } 133 getRows()134 public int getRows() { 135 return nativeGetRows(mNativePtr); 136 } 137 getCols()138 public int getCols() { 139 return nativeGetCols(mNativePtr); 140 } 141 getScrollRows()142 public int getScrollRows() { 143 return nativeGetScrollRows(mNativePtr); 144 } 145 getCellRun(int row, int col, CellRun run)146 public void getCellRun(int row, int col, CellRun run) { 147 if (nativeGetCellRun(mNativePtr, row, col, run) != 0) { 148 throw new IllegalStateException("getCell failed"); 149 } 150 } 151 getTitle()152 public String getTitle() { 153 // TODO: hook up to title passed through termprop 154 return mTitle; 155 } 156 dispatchKey(int modifiers, int key)157 public boolean dispatchKey(int modifiers, int key) { 158 return nativeDispatchKey(mNativePtr, modifiers, key); 159 } 160 dispatchCharacter(int modifiers, int character)161 public boolean dispatchCharacter(int modifiers, int character) { 162 return nativeDispatchCharacter(mNativePtr, modifiers, character); 163 } 164 nativeInit(TerminalCallbacks callbacks, int rows, int cols)165 private static native long nativeInit(TerminalCallbacks callbacks, int rows, int cols); nativeDestroy(long ptr)166 private static native int nativeDestroy(long ptr); 167 nativeRun(long ptr)168 private static native int nativeRun(long ptr); nativeResize(long ptr, int rows, int cols, int scrollRows)169 private static native int nativeResize(long ptr, int rows, int cols, int scrollRows); nativeGetCellRun(long ptr, int row, int col, CellRun run)170 private static native int nativeGetCellRun(long ptr, int row, int col, CellRun run); nativeGetRows(long ptr)171 private static native int nativeGetRows(long ptr); nativeGetCols(long ptr)172 private static native int nativeGetCols(long ptr); nativeGetScrollRows(long ptr)173 private static native int nativeGetScrollRows(long ptr); 174 nativeDispatchKey(long ptr, int modifiers, int key)175 private static native boolean nativeDispatchKey(long ptr, int modifiers, int key); nativeDispatchCharacter(long ptr, int modifiers, int character)176 private static native boolean nativeDispatchCharacter(long ptr, int modifiers, int character); 177 } 178