Next: , Previous: , Up: EmacstとAndroid   [Contents][Index]


H.5 AndroidでのEmacsの実行

ユーザーから見るとAndroidはほとんど単一ユーザー向けのオペレーティングシステムです。ただしアプリケーションやEmacsの視点からは、非常に多数のユーザーにホストするシステムなのです。

アプリケーションはそれぞれ独自のホームディレクトリー(アプリケーションのアプリケーションデータディレクトリー; AndroidでEmacsがアクセスできるファイルを参照)をセットされて、独自のユーザーにより実行されます。28

アプリケーションはそれぞれ、多くのシステムディレクトリーや他のアプリケーションのアプリケーションデータディレクトリへのアクセスも禁止されています。

Emacsの配布物には複数のバイナリーも含まれています。実行可能ファイルはライブラリーディレクトリーにパッケージされます。そうしないとEmacsのインストールにおいて、システムがそれらをパッケージ展開しないからです。これはctagsemacsclientをサブプロセスで起動する際に、Lispコードがかわりにlibctags.solibemacsclient.soをコマンドライン指定しなければならないことを意味しています。どの名前を使用するかは変数ctags-program-nameetags-program-namehexl-program-nameemacsclient-program-namemovemail-program-nameebrowse-program-namercs2log-program-nameの値を調べて判断します。Subprocess Creation in the Emacs Lisp Reference Manualを参照してください。

The /assets directory containing Emacs start-up files is meant to be inaccessible to processes not directly created by zygote, the system service responsible for starting applications. Since required Lisp is found in the /assets directory, it would thus follow that it is not possible for Emacs to start itself as a subprocess. A special binary named libandroid-emacs.so is provided with Emacs, which is installed into the library directory, and which tries its best to start Emacs for the purpose of running Lisp in batch mode. The approach it takes was devised by reference to Android source code, and is not sanctioned by the Android compatibility definition documents, so your mileage may vary.

Even when the location of the libandroid-emacs.so command is known in advance, special preparation is required to run Emacs from elsewhere than a subprocess of an existing Emacs session, as it must be made to understand the location of resources and shared libraries in or extracted from the installed application package. The OS command pm path org.gnu.emacs will print the location of the application package, though the said command must be invoked in a peculiar manner to satisfy system restrictions on communication between pseudoterminal devices created by user applications and system services such as the package manager, which is to say, with the standard IO streams redirected to a real file or a pipe. This value, once established, must be specified in the environment variables EMACS_CLASS_PATH, so that this sample shell script may be installed as emacs in any location that is accessible:

#!/system/bin/sh

package_name=`pm path org.gnu.emacs 2>/dev/null </dev/null \
               | sed 's/^package://'`
emacs=
EMACS_CLASS_PATH=$package_name

for libdir in `dirname $package_name`/lib/*; do
  ld_path=${ld_path:+${ld_path}:}$libdir
  test -x "$libdir"/libandroid-emacs.so \
    && emacs="$libdir"/libandroid-emacs.so
done

export EMACS_CLASS_PATH
test -x "$emacs" || exit 1
exec $emacs "$@"

Android 10以降では表向きはセキュリティー上の懸念という理由により、Emacs自体がアプリケーションデータディレクトリーにある実行可能ファイルを実行することも禁止されました。それらのシステムでは、通常はEmacsが回避策を講じます。ただしこの回避策には実行可能ファイルのロードを実装して、その子プロセスすべてにトレースを適用するような別プロセスを介して、すべてのサブプロセスを実行することが要求されます。これは様々な理由により問題が生じる可能性があるのです。そのような場合には変数android-use-exec-loadernilに変更することで、この回避策を無効にできます。

この回避策が効力をもつ間は、process-id関数によって取得されるプロセスIDはその実行可能ローダーのプロセスIDとなります。実行可能ローダーの子プロセスは実行可能ローダーと同じプロセスグループに所属するからです。したがってinterrupt-processやその他の関連する関数は正しく機能しますが、他の目的のためにprocess-idがリターンしたプロセスIDを用いても正しく機能しないでしょう。

このプロセスのトレースが実行されるメカニズムから派生する影響の1つとして、内部シェル(対話的なサブシェルを参照)の内部のジョブ制御機能がプロセスを停止できなくなり、EmacsがサブプロセスにたいしてSIGSTOPシグナルを生成しても効果はないでしょう。

さらにAndroid 12ではEmacs自体がバックグラウンドの間に、CPUを消費するサブプロセスも終了させられます。システムはCPUを過剰に消費するプロセスを5分間隔で判定して、もっともCPU時間を多く消費するプロセスを終了させるのです。

Android 12.1およびAndroid 13ではこの挙動を無効にするオプションが提供されています。これを行うには“USB debugging”(AndroidでのEmacsの起動を参照)を有効にして別のシステムからAndroidシステムに接続して以下を実行してください:

$ adb shell "settings put global settings_enable_monitor_phantom_procs false"

オペレーティングシステムに適用される“Languages & Input(言語と入力)”の設定は、プログラムにたいするCのlocaleセットには影響しませんが、Emacsには起動の間に考慮されます。選択された言語と地域バリアントからlocale名が生成されて、それにもとづいた言語環境(言語環境を参照)が選択されます。これがLANGやその他のlocale関連の環境変数をオーバーライドすることはありません。この方法によってセットされた言語環境にたいするコーディングシステムは、例外なくutf-8-unixになります。

EmacsがAndroid 5.0以降で開始された際には、環境変数LANG (一般的な変数を参照)はen_US.utf8にセットされます。これによりAndroidのCライブラリーにリンクされたサブプロセスが出力を適切にプリントできるようになります。それ以前のバージョンのAndroidでは何のlocaleも実装されておらず、そのためこの変数はCにセットされます。

アプリケーションプロセスはシステムによって使い捨て可能なエンティティとして扱われます。Emacsのすべてのフレームがバックグラウンドに移動されると、システムリソースを節約するために、任意のタイミングでEmacsが終了させられる可能性があります。

Android 7.1以前ではメモリー負荷がないかぎりシステムがEmacsをkillしないように、Emacsが自身を“バックグラウンドサービス”に指定します。

Android 8.0ではそのようなバックグラウンドサービスを特別に扱う機能が削除されました。とはいえEmacsには回避策があります。システムは永続的に通知を作成するアプリケーションはアクティブな作業を行っているとみなして、そのようなアプリケーションのkillを回避します。したがってそのようなシステムでは、Emacsが実行されているかぎり通知が永続的に表示されます。

バージョン13より前のAndroidでは、Emacsが通知を表示する権限は不要です。Android 13以降では、ユーザーがEmacsにそのような権限を与えるまで通知は表示されません。それにも関わらず、単に通知の表示を試みるだけで突然死を避けるには十分なのです。通知が表示されるかどうかがバックグラウンドにおけるEmacsの実行能力を損なうことはないので、通知を無効にしても問題はないでしょう。

とはいえシステムがEmacsをkillしない保証はありません。Open Handset AllianceのAndroidのサンプル実装は正しく振る舞うとはいえ、多くのメーカーのプロプライエタリーなバージョンのAndroidには、バックグラウンドにおけるプログラムの実行に追加の制限が設けられているのです。https://dontkillmyapp.com/にはそのような問題のあるメーカー、および場合によっては回避策となるようなリストがあります。

AndroidにはEmacsにアクセスできるシステムサービスを判定する権限システムも定義されています。プログラムは欲する権限を指定しなければなりません。その後に何が起こるかは、使用しているAndroidのバージョン次第です。


Footnotes

(28)

“共有ユーザーID(shared user ID)”を指定して、同じ‘パッケージ署名キー(‘package signing key)”を用いて署名、インストールされた他のアプリケーションは除外される。このような場合にはEmacsは同じユーザーで実行されるとともに、前述のアプリケーションそれぞれにたいして同じアクセス権を保有する。


Next: Androidのウィンドウシステム, Previous: Androidでの他のプログラムからのファイルアクセス, Up: EmacstとAndroid   [Contents][Index]

This page has generated for branch:work/emacs-30_11e7ae3964e192b0e4bcc437a04278ee727e720b, commit:b3c5971e7766c1bed458d4837c2a2eafc0760e6a to check Japanese translation.