mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 21:07:58 +02:00
* android:
+ API to write to the Android system log. + API to redirect standard output and error to the Android system log. The redirection is performed automatically for shared libraries loaded by Java applications. git-svn-id: trunk@34352 -
This commit is contained in:
parent
3822515bd9
commit
419c6ce61e
@ -83,3 +83,147 @@ begin
|
||||
end;
|
||||
Result:=_ApiLevel;
|
||||
end;
|
||||
|
||||
// ************* Android log
|
||||
|
||||
var
|
||||
DefaultLogTag: string[20];
|
||||
|
||||
function __android_log_write(prio: longint; tag, text: pchar): longint; cdecl; external 'log' name '__android_log_write';
|
||||
|
||||
procedure SysLogWrite(Priority: longint; Tag, Msg: PAnsiChar);
|
||||
begin
|
||||
__android_log_write(Priority, Tag, Msg);
|
||||
end;
|
||||
|
||||
procedure SysLogWrite(Priority: longint; Msg: PAnsiChar);
|
||||
begin
|
||||
SysLogWrite(Priority, @DefaultLogTag[1], Msg);
|
||||
end;
|
||||
|
||||
procedure SysLogWrite(Msg: PAnsiChar);
|
||||
begin
|
||||
SysLogWrite(DefaultSysLogPriority, @DefaultLogTag[1], Msg);
|
||||
end;
|
||||
|
||||
// ************* STDIO redirection to Android log
|
||||
|
||||
const
|
||||
IOBufferLength = 512;
|
||||
var
|
||||
IOBuf : array[0..IOBufferLength] of char;
|
||||
IOLen : SizeInt;
|
||||
IORedirected: boolean;
|
||||
|
||||
procedure OutputIOBuffer(Var F: TextRec);
|
||||
var
|
||||
p: longint;
|
||||
begin
|
||||
if (@F = @ErrOutput) or (@F = @StdErr) then
|
||||
p:=ANDROID_LOG_ERROR
|
||||
else
|
||||
p:=DefaultSysLogPriority;
|
||||
SysLogWrite(p, IOBuf);
|
||||
IOLen:=0;
|
||||
end;
|
||||
|
||||
procedure IOWrite(Var F: TextRec);
|
||||
var
|
||||
i, len : SizeInt;
|
||||
Begin
|
||||
while F.BufPos>0 do
|
||||
begin
|
||||
begin
|
||||
if F.BufPos + IOLen > IOBufferLength then
|
||||
len:=IOBufferLength - IOLen
|
||||
else
|
||||
len:=F.BufPos;
|
||||
i:=0;
|
||||
while i < len do
|
||||
begin
|
||||
if F.bufptr^[i] in [#10, #13] then
|
||||
begin
|
||||
IOBuf[IOLen]:=#0;
|
||||
OutputIOBuffer(F);
|
||||
Inc(i);
|
||||
if (i < len) and (F.bufptr^[i - 1] = #13) and (F.bufptr^[i] = #10) then
|
||||
Inc(i);
|
||||
end
|
||||
else
|
||||
begin
|
||||
IOBuf[IOLen]:=F.bufptr^[i];
|
||||
Inc(IOLen);
|
||||
Inc(i);
|
||||
end;
|
||||
end;
|
||||
IOBuf[IOLen]:=#0;
|
||||
end;
|
||||
if IOLen = IOBufferLength then
|
||||
OutputIOBuffer(F);
|
||||
Dec(F.BufPos, len);
|
||||
end;
|
||||
End;
|
||||
|
||||
procedure IOClose(Var F: TextRec);
|
||||
begin
|
||||
if IOLen > 0 then
|
||||
OutputIOBuffer(F);
|
||||
end;
|
||||
|
||||
procedure IOOpen(Var F: TextRec);
|
||||
Begin
|
||||
TextRec(F).InOutFunc:=@IOWrite;
|
||||
TextRec(F).FlushFunc:=@IOWrite;
|
||||
TextRec(F).CloseFunc:=@IOClose;
|
||||
IOLen:=0;
|
||||
End;
|
||||
|
||||
procedure RedirectFile(Var T: Text);
|
||||
begin
|
||||
Assign(T,'');
|
||||
TextRec(T).OpenFunc:=@IOOpen;
|
||||
Rewrite(T);
|
||||
end;
|
||||
|
||||
procedure RedirectOutputToSysLog;
|
||||
begin
|
||||
if IORedirected then exit;
|
||||
IORedirected:=True;
|
||||
RedirectFile(Output);
|
||||
RedirectFile(StdOut);
|
||||
RedirectFile(ErrOutput);
|
||||
RedirectFile(StdErr);
|
||||
end;
|
||||
|
||||
procedure SetDefaultSysLogTag(const Tag: string);
|
||||
var
|
||||
len: longint;
|
||||
begin
|
||||
DefaultLogTag:=Tag;
|
||||
len:=Length(DefaultLogTag);
|
||||
if len = High(DefaultLogTag) then
|
||||
Dec(len);
|
||||
DefaultLogTag[len + 1]:=#0;
|
||||
end;
|
||||
|
||||
procedure InitAndroid;
|
||||
var
|
||||
i: integer;
|
||||
s: string;
|
||||
begin
|
||||
IsJniLibrary:=IsLibrary and (Pos('/system/', ParamStr(0)) = 1);
|
||||
if IsJniLibrary then
|
||||
begin
|
||||
// The library is loaded by a Java app. The proper tag will be set by SysUtils.
|
||||
SetDefaultSysLogTag('FPC');
|
||||
RedirectOutputToSysLog;
|
||||
end
|
||||
else
|
||||
begin
|
||||
s:=ParamStr(0);
|
||||
i:=Length(s);
|
||||
while (i > 0) and (s[i] <> '/') do
|
||||
Dec(i);
|
||||
SetDefaultSysLogTag(Copy(s, i + 1, MaxInt));
|
||||
end;
|
||||
end;
|
||||
|
@ -3,7 +3,7 @@
|
||||
Copyright (c) 2016 by Yury Sidorov,
|
||||
member of the Free Pascal development team.
|
||||
|
||||
Android-specific part of the System unit.
|
||||
Header of Android-specific part of the System unit.
|
||||
|
||||
See the file COPYING.FPC, included in this distribution,
|
||||
for details about the copyright.
|
||||
@ -13,7 +13,36 @@
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**********************************************************************}
|
||||
|
||||
// Returns an Android system property
|
||||
const
|
||||
// Android system log priority
|
||||
ANDROID_LOG_VERBOSE = 2;
|
||||
ANDROID_LOG_DEBUG = 3;
|
||||
ANDROID_LOG_INFO = 4;
|
||||
ANDROID_LOG_WARN = 5;
|
||||
ANDROID_LOG_ERROR = 6;
|
||||
ANDROID_LOG_FATAL = 7;
|
||||
|
||||
// Default priority for syslog messages.
|
||||
var DefaultSysLogPriority: longint = ANDROID_LOG_DEBUG;
|
||||
|
||||
// Set default tag for syslog messages. Initially the tag is set to the current module name.
|
||||
procedure SetDefaultSysLogTag(const Tag: string);
|
||||
|
||||
// Write a message to the Android system log.
|
||||
procedure SysLogWrite(Priority: longint; Tag, Msg: PAnsiChar); overload;
|
||||
procedure SysLogWrite(Priority: longint; Msg: PAnsiChar); overload;
|
||||
procedure SysLogWrite(Msg: PAnsiChar); overload;
|
||||
|
||||
// Redirects standard output and error to the Android system log.
|
||||
// The redirection is performed automatically for shared libraries loaded by Java applications.
|
||||
procedure RedirectOutputToSysLog;
|
||||
|
||||
// Returns an Android system property.
|
||||
function GetSystemProperty(Name: PAnsiChar): shortstring;
|
||||
// Returns an Android API level of the current system
|
||||
|
||||
// Returns an Android API level of the host system.
|
||||
function SystemApiLevel: shortint;
|
||||
|
||||
// True when the current program is a shared library loaded by a Java application.
|
||||
var IsJniLibrary: boolean;
|
||||
|
||||
|
@ -378,6 +378,9 @@ begin
|
||||
InitSystemThreads;
|
||||
{ dynamic libraries }
|
||||
InitSystemDynLibs;
|
||||
{$ifdef android}
|
||||
InitAndroid;
|
||||
{$endif android}
|
||||
{ restore original signal handlers in case this is a library }
|
||||
if IsLibrary then
|
||||
RestoreOldSignalHandlers;
|
||||
|
@ -80,6 +80,9 @@ procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);
|
||||
implementation
|
||||
|
||||
Uses
|
||||
{$ifdef android}
|
||||
dl,
|
||||
{$endif android}
|
||||
{$ifdef FPC_USE_LIBC}initc{$ELSE}Syscall{$ENDIF}, Baseunix, unixutil;
|
||||
|
||||
type
|
||||
@ -1428,7 +1431,6 @@ end;
|
||||
|
||||
var
|
||||
_HomeDir: string;
|
||||
IsNDKLib: boolean;
|
||||
|
||||
Function GetHomeDir : String;
|
||||
var
|
||||
@ -1438,7 +1440,7 @@ begin
|
||||
Result:=_HomeDir;
|
||||
if Result <> '' then
|
||||
exit;
|
||||
if IsLibrary then
|
||||
if IsJniLibrary then
|
||||
begin
|
||||
// For shared library get the package name of a host Java application
|
||||
h:=FileOpen('/proc/self/cmdline', fmOpenRead or fmShareDenyNone);
|
||||
@ -1449,8 +1451,8 @@ begin
|
||||
SetLength(Result, strlen(PChar(Result)));
|
||||
FileClose(h);
|
||||
Result:='/data/data/' + Result;
|
||||
IsNDKLib:=DirectoryExists(Result);
|
||||
if IsNDKLib then
|
||||
IsJniLibrary:=DirectoryExists(Result);
|
||||
if IsJniLibrary then
|
||||
Result:=Result + '/files/'
|
||||
else
|
||||
Result:=''; // No package
|
||||
@ -1497,7 +1499,7 @@ begin
|
||||
else
|
||||
Result:=IncludeTrailingPathDelimiter(XdgConfigHome);
|
||||
{$ifdef android}
|
||||
if IsNDKLib then
|
||||
if IsJniLibrary then
|
||||
exit;
|
||||
{$endif android}
|
||||
if VendorName<>'' then
|
||||
@ -1513,7 +1515,7 @@ begin
|
||||
else
|
||||
Result:=IncludeTrailingPathDelimiter(XdgConfigHome);
|
||||
{$ifdef android}
|
||||
if IsNDKLib then
|
||||
if IsJniLibrary then
|
||||
begin
|
||||
Result:=Result+'config'+ConfigExtension;
|
||||
exit;
|
||||
@ -1596,6 +1598,26 @@ begin
|
||||
Result := -Tzseconds div 60;
|
||||
end;
|
||||
|
||||
{$ifdef android}
|
||||
|
||||
procedure InitAndroid;
|
||||
var
|
||||
dlinfo: dl_info;
|
||||
s: string;
|
||||
begin
|
||||
if IsJniLibrary then
|
||||
begin
|
||||
FillChar(dlinfo, sizeof(dlinfo), 0);
|
||||
dladdr(@InitAndroid, @dlinfo);
|
||||
s:=dlinfo.dli_fname;
|
||||
if s <> '' then
|
||||
SetDefaultSysLogTag(ExtractFileName(s));
|
||||
end;
|
||||
end;
|
||||
|
||||
{$endif android}
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
Initialization code
|
||||
****************************************************************************}
|
||||
@ -1605,7 +1627,10 @@ Initialization
|
||||
InitInternational; { Initialize internationalization settings }
|
||||
SysConfigDir:='/etc'; { Initialize system config dir }
|
||||
OnBeep:=@SysBeep;
|
||||
|
||||
{$ifdef android}
|
||||
InitAndroid;
|
||||
{$endif android}
|
||||
|
||||
Finalization
|
||||
FreeDriveStr;
|
||||
DoneExceptions;
|
||||
|
Loading…
Reference in New Issue
Block a user