/* * Copyright (C) 2012 Steven Luo * * 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 jackpal.androidterm; import java.io.File; import java.io.IOException; import java.util.UUID; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; import android.util.Log; import jackpal.androidterm.emulatorview.TermSession; import jackpal.androidterm.util.SessionList; import jackpal.androidterm.util.TermSettings; public class RemoteInterface extends Activity { protected static final String PRIVACT_OPEN_NEW_WINDOW = "jackpal.androidterm.private.OPEN_NEW_WINDOW"; protected static final String PRIVACT_SWITCH_WINDOW = "jackpal.androidterm.private.SWITCH_WINDOW"; protected static final String PRIVEXTRA_TARGET_WINDOW = "jackpal.androidterm.private.target_window"; protected static final String PRIVACT_ACTIVITY_ALIAS = "jackpal.androidterm.TermInternal"; private TermSettings mSettings; private TermService mTermService; private Intent mTSIntent; private ServiceConnection mTSConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { TermService.TSBinder binder = (TermService.TSBinder) service; mTermService = binder.getService(); handleIntent(); } public void onServiceDisconnected(ComponentName className) { mTermService = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mSettings = new TermSettings(getResources(), prefs); Intent TSIntent = new Intent(this, TermService.class); mTSIntent = TSIntent; startService(TSIntent); if (!bindService(TSIntent, mTSConnection, BIND_AUTO_CREATE)) { Log.e(TermDebug.LOG_TAG, "bind to service failed!"); finish(); } } @Override public void finish() { ServiceConnection conn = mTSConnection; if (conn != null) { unbindService(conn); // Stop the service if no terminal sessions are running TermService service = mTermService; if (service != null) { SessionList sessions = service.getSessions(); if (sessions == null || sessions.size() == 0) { stopService(mTSIntent); } } mTSConnection = null; mTermService = null; } super.finish(); } protected TermService getTermService() { return mTermService; } protected void handleIntent() { TermService service = getTermService(); if (service == null) { finish(); return; } Intent myIntent = getIntent(); String action = myIntent.getAction(); if (action.equals(Intent.ACTION_SEND) && myIntent.hasExtra(Intent.EXTRA_STREAM)) { /* "permission.RUN_SCRIPT" not required as this is merely opening a new window. */ Object extraStream = myIntent.getExtras().get(Intent.EXTRA_STREAM); if (extraStream instanceof Uri) { String path = ((Uri) extraStream).getPath(); File file = new File(path); String dirPath = file.isDirectory() ? path : file.getParent(); openNewWindow("cd " + quoteForBash(dirPath)); } } else { // Intent sender may not have permissions, ignore any extras openNewWindow(null); } finish(); } /** * Quote a string so it can be used as a parameter in bash and similar shells. */ public static String quoteForBash(String s) { StringBuilder builder = new StringBuilder(); String specialChars = "\"\\$`!"; builder.append('"'); int length = s.length(); for (int i = 0; i < length; i++) { char c = s.charAt(i); if (specialChars.indexOf(c) >= 0) { builder.append('\\'); } builder.append(c); } builder.append('"'); return builder.toString(); } protected String openNewWindow(String iInitialCommand) { TermService service = getTermService(); String initialCommand = mSettings.getInitialCommand(); if (iInitialCommand != null) { if (initialCommand != null) { initialCommand += "\r" + iInitialCommand; } else { initialCommand = iInitialCommand; } } try { TermSession session = Term.createTermSession(this, mSettings, initialCommand); session.setFinishCallback(service); service.getSessions().add(session); String handle = UUID.randomUUID().toString(); ((GenericTermSession) session).setHandle(handle); Intent intent = new Intent(PRIVACT_OPEN_NEW_WINDOW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); return handle; } catch (IOException e) { return null; } } protected String appendToWindow(String handle, String iInitialCommand) { TermService service = getTermService(); // Find the target window SessionList sessions = service.getSessions(); GenericTermSession target = null; int index; for (index = 0; index < sessions.size(); ++index) { GenericTermSession session = (GenericTermSession) sessions.get(index); String h = session.getHandle(); if (h != null && h.equals(handle)) { target = session; break; } } if (target == null) { // Target window not found, open a new one return openNewWindow(iInitialCommand); } if (iInitialCommand != null) { target.write(iInitialCommand); target.write('\r'); } Intent intent = new Intent(PRIVACT_SWITCH_WINDOW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(PRIVEXTRA_TARGET_WINDOW, index); startActivity(intent); return handle; } }