aboutsummaryrefslogtreecommitdiff
path: root/xbmc/platform/android/activity/android_main.cpp
blob: 3970e78f49e60f88fe1d32cf54cdac5832e11783 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 *  Copyright (C) 2012-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "EventLoop.h"
#include "XBMCApp.h"

#include "platform/android/activity/JNIMainActivity.h"
#include "platform/android/activity/JNIXBMCAudioManagerOnAudioFocusChangeListener.h"
#include "platform/android/activity/JNIXBMCBroadcastReceiver.h"
#include "platform/android/activity/JNIXBMCConnectivityManagerNetworkCallback.h"
#include "platform/android/activity/JNIXBMCDisplayManagerDisplayListener.h"
#include "platform/android/activity/JNIXBMCFile.h"
#include "platform/android/activity/JNIXBMCJsonHandler.h"
#include "platform/android/activity/JNIXBMCMainView.h"
#include "platform/android/activity/JNIXBMCMediaSession.h"
#include "platform/android/activity/JNIXBMCNsdManagerDiscoveryListener.h"
#include "platform/android/activity/JNIXBMCNsdManagerRegistrationListener.h"
#include "platform/android/activity/JNIXBMCNsdManagerResolveListener.h"
#include "platform/android/activity/JNIXBMCSpeechRecognitionListener.h"
#include "platform/android/activity/JNIXBMCSurfaceTextureOnFrameAvailableListener.h"
#include "platform/android/activity/JNIXBMCURIUtils.h"
#include "platform/android/activity/JNIXBMCVideoView.h"

#include <stdint.h>
#include <stdio.h>
#include <thread>

#include <unistd.h>

using namespace jni;

namespace
{

class LogRedirector
{
  // redirect stdout / stderr to logcat
  // based on https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/

public:
  LogRedirector()
  {
    // make stdout line-buffered and stderr unbuffered
    setvbuf(stdout, 0, _IOLBF, 0);
    setvbuf(stderr, 0, _IONBF, 0);

    // spawn the logging thread
    std::thread thread(&LogRedirector::Run);
    thread.detach();
  }

private:
  static void Run()
  {
    // create a pipe and redirect stdout and stderr
    int pfds[2];
    pipe(pfds);
    dup2(pfds[1], STDOUT_FILENO);
    dup2(pfds[1], STDERR_FILENO);

    ssize_t rdsz;
    char buf[128];
    while ((rdsz = read(pfds[0], buf, sizeof(buf) - 1)) > 0)
    {
      if (buf[rdsz - 1] == '\n')
        --rdsz;

      buf[rdsz] = 0; // add null-terminator
      __android_log_write(ANDROID_LOG_DEBUG, "Kodi", buf);
    }
  }
};

LogRedirector g_LogRedirector;

} // namespace

extern void android_main(struct android_app* state)
{
  {
    CEventLoop eventLoop(state);
    IInputHandler inputHandler;
    CXBMCApp& theApp = CXBMCApp::Create(state->activity, inputHandler);
    if (theApp.isValid())
    {
      eventLoop.run(theApp, inputHandler);
      theApp.Quit();
    }
    else
      CXBMCApp::android_printf("android_main: setup failed");

    CXBMCApp::android_printf("android_main: Exiting");

    CXBMCApp::Destroy();
  }
  // We need to call exit() so that all loaded libraries are properly unloaded
  // otherwise on the next start of the Activity android will simply re-use
  // those loaded libs in the state they were in when we quit Kodi last time
  // which will lead to crashes because of global/static classes that haven't
  // been properly uninitialized
  exit(0);
}

extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  jint version = JNI_VERSION_1_6;
  JNIEnv* env;
  if (vm->GetEnv(reinterpret_cast<void**>(&env), version) != JNI_OK)
    return -1;

  CJNIMainActivity::RegisterNatives(env);
  CJNIXBMCAudioManagerOnAudioFocusChangeListener::RegisterNatives(env);
  CJNIXBMCBroadcastReceiver::RegisterNatives(env);
  CJNIXBMCConnectivityManagerNetworkCallback::RegisterNatives(env);
  CJNIXBMCDisplayManagerDisplayListener::RegisterNatives(env);
  CJNIXBMCFile::RegisterNatives(env);
  CJNIXBMCJsonHandler::RegisterNatives(env);
  CJNIXBMCMainView::RegisterNatives(env);
  CJNIXBMCMediaSession::RegisterNatives(env);
  CJNIXBMCNsdManagerDiscoveryListener::RegisterNatives(env);
  CJNIXBMCNsdManagerRegistrationListener::RegisterNatives(env);
  CJNIXBMCNsdManagerResolveListener::RegisterNatives(env);
  CJNIXBMCSpeechRecognitionListener::RegisterNatives(env);
  CJNIXBMCSurfaceTextureOnFrameAvailableListener::RegisterNatives(env);
  CJNIXBMCURIUtils::RegisterNatives(env);
  CJNIXBMCVideoView::RegisterNatives(env);

  return version;
}