100e305d2STamas Berghammer //===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
200e305d2STamas Berghammer //
300e305d2STamas Berghammer //                     The LLVM Compiler Infrastructure
400e305d2STamas Berghammer //
500e305d2STamas Berghammer // This file is distributed under the University of Illinois Open Source
600e305d2STamas Berghammer // License. See LICENSE.TXT for details.
700e305d2STamas Berghammer //
800e305d2STamas Berghammer //===----------------------------------------------------------------------===//
900e305d2STamas Berghammer 
1000e305d2STamas Berghammer // C Includes
1100e305d2STamas Berghammer // C++ Includes
1200e305d2STamas Berghammer // Other libraries and framework includes
1300e305d2STamas Berghammer #include "lldb/Core/Log.h"
1400e305d2STamas Berghammer #include "lldb/Core/PluginManager.h"
151c6a1ea9STamas Berghammer #include "lldb/Host/HostInfo.h"
1600e305d2STamas Berghammer 
1700e305d2STamas Berghammer // Project includes
18*6f001068SOleksiy Vyalov #include "AdbClient.h"
1900e305d2STamas Berghammer #include "PlatformAndroid.h"
2000e305d2STamas Berghammer #include "PlatformAndroidRemoteGDBServer.h"
2100e305d2STamas Berghammer 
2200e305d2STamas Berghammer using namespace lldb;
2300e305d2STamas Berghammer using namespace lldb_private;
2400e305d2STamas Berghammer 
2500e305d2STamas Berghammer static uint32_t g_initialize_count = 0;
2600e305d2STamas Berghammer 
2700e305d2STamas Berghammer void
2800e305d2STamas Berghammer PlatformAndroid::Initialize ()
2900e305d2STamas Berghammer {
303c4f89d7STamas Berghammer     PlatformLinux::Initialize ();
313c4f89d7STamas Berghammer 
3200e305d2STamas Berghammer     if (g_initialize_count++ == 0)
3300e305d2STamas Berghammer     {
341c6a1ea9STamas Berghammer #if defined(__ANDROID__)
351c6a1ea9STamas Berghammer         PlatformSP default_platform_sp (new PlatformAndroid(true));
361c6a1ea9STamas Berghammer         default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
371c6a1ea9STamas Berghammer         Platform::SetHostPlatform (default_platform_sp);
381c6a1ea9STamas Berghammer #endif
391c6a1ea9STamas Berghammer         PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
401c6a1ea9STamas Berghammer                                        PlatformAndroid::GetPluginDescriptionStatic(false),
4100e305d2STamas Berghammer                                        PlatformAndroid::CreateInstance);
4200e305d2STamas Berghammer     }
4300e305d2STamas Berghammer }
4400e305d2STamas Berghammer 
4500e305d2STamas Berghammer void
4600e305d2STamas Berghammer PlatformAndroid::Terminate ()
4700e305d2STamas Berghammer {
4800e305d2STamas Berghammer     if (g_initialize_count > 0)
4900e305d2STamas Berghammer     {
5000e305d2STamas Berghammer         if (--g_initialize_count == 0)
5100e305d2STamas Berghammer         {
5200e305d2STamas Berghammer             PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
5300e305d2STamas Berghammer         }
5400e305d2STamas Berghammer     }
553c4f89d7STamas Berghammer 
563c4f89d7STamas Berghammer     PlatformLinux::Terminate ();
5700e305d2STamas Berghammer }
5800e305d2STamas Berghammer 
5900e305d2STamas Berghammer PlatformSP
6000e305d2STamas Berghammer PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
6100e305d2STamas Berghammer {
6200e305d2STamas Berghammer     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
6300e305d2STamas Berghammer     if (log)
6400e305d2STamas Berghammer     {
6500e305d2STamas Berghammer         const char *arch_name;
6600e305d2STamas Berghammer         if (arch && arch->GetArchitectureName ())
6700e305d2STamas Berghammer             arch_name = arch->GetArchitectureName ();
6800e305d2STamas Berghammer         else
6900e305d2STamas Berghammer             arch_name = "<null>";
7000e305d2STamas Berghammer 
7100e305d2STamas Berghammer         const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
7200e305d2STamas Berghammer 
7300e305d2STamas Berghammer         log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
7400e305d2STamas Berghammer     }
7500e305d2STamas Berghammer 
7600e305d2STamas Berghammer     bool create = force;
7700e305d2STamas Berghammer     if (create == false && arch && arch->IsValid())
7800e305d2STamas Berghammer     {
7900e305d2STamas Berghammer         const llvm::Triple &triple = arch->GetTriple();
8000e305d2STamas Berghammer         switch (triple.getVendor())
8100e305d2STamas Berghammer         {
8200e305d2STamas Berghammer             case llvm::Triple::PC:
8300e305d2STamas Berghammer                 create = true;
8400e305d2STamas Berghammer                 break;
8500e305d2STamas Berghammer 
8600e305d2STamas Berghammer #if defined(__ANDROID__)
8700e305d2STamas Berghammer             // Only accept "unknown" for the vendor if the host is android and
8800e305d2STamas Berghammer             // it "unknown" wasn't specified (it was just returned because it
8900e305d2STamas Berghammer             // was NOT specified_
9000e305d2STamas Berghammer             case llvm::Triple::VendorType::UnknownVendor:
9100e305d2STamas Berghammer                 create = !arch->TripleVendorWasSpecified();
9200e305d2STamas Berghammer                 break;
9300e305d2STamas Berghammer #endif
9400e305d2STamas Berghammer             default:
9500e305d2STamas Berghammer                 break;
9600e305d2STamas Berghammer         }
9700e305d2STamas Berghammer 
9800e305d2STamas Berghammer         if (create)
9900e305d2STamas Berghammer         {
10000e305d2STamas Berghammer             switch (triple.getOS())
10100e305d2STamas Berghammer             {
1021c6a1ea9STamas Berghammer                 case llvm::Triple::Android:
10300e305d2STamas Berghammer                     break;
10400e305d2STamas Berghammer 
10500e305d2STamas Berghammer #if defined(__ANDROID__)
10600e305d2STamas Berghammer                 // Only accept "unknown" for the OS if the host is android and
10700e305d2STamas Berghammer                 // it "unknown" wasn't specified (it was just returned because it
10800e305d2STamas Berghammer                 // was NOT specified)
10900e305d2STamas Berghammer                 case llvm::Triple::OSType::UnknownOS:
11000e305d2STamas Berghammer                     create = !arch->TripleOSWasSpecified();
11100e305d2STamas Berghammer                     break;
11200e305d2STamas Berghammer #endif
11300e305d2STamas Berghammer                 default:
11400e305d2STamas Berghammer                     create = false;
11500e305d2STamas Berghammer                     break;
11600e305d2STamas Berghammer             }
11700e305d2STamas Berghammer         }
11800e305d2STamas Berghammer     }
11900e305d2STamas Berghammer 
12000e305d2STamas Berghammer     if (create)
12100e305d2STamas Berghammer     {
12200e305d2STamas Berghammer         if (log)
12300e305d2STamas Berghammer             log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
1241c6a1ea9STamas Berghammer         return PlatformSP(new PlatformAndroid(false));
12500e305d2STamas Berghammer     }
12600e305d2STamas Berghammer 
12700e305d2STamas Berghammer     if (log)
12800e305d2STamas Berghammer         log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);
12900e305d2STamas Berghammer 
13000e305d2STamas Berghammer     return PlatformSP();
13100e305d2STamas Berghammer }
13200e305d2STamas Berghammer 
1331c6a1ea9STamas Berghammer PlatformAndroid::PlatformAndroid (bool is_host) :
1341c6a1ea9STamas Berghammer     PlatformLinux(is_host)
13500e305d2STamas Berghammer {
13600e305d2STamas Berghammer }
13700e305d2STamas Berghammer 
13800e305d2STamas Berghammer PlatformAndroid::~PlatformAndroid()
13900e305d2STamas Berghammer {
14000e305d2STamas Berghammer }
14100e305d2STamas Berghammer 
14200e305d2STamas Berghammer lldb_private::ConstString
1431c6a1ea9STamas Berghammer PlatformAndroid::GetPluginNameStatic (bool is_host)
1441c6a1ea9STamas Berghammer {
1451c6a1ea9STamas Berghammer     if (is_host)
1461c6a1ea9STamas Berghammer     {
1471c6a1ea9STamas Berghammer         static ConstString g_host_name(Platform::GetHostPlatformName ());
1481c6a1ea9STamas Berghammer         return g_host_name;
1491c6a1ea9STamas Berghammer     }
1501c6a1ea9STamas Berghammer     else
15100e305d2STamas Berghammer     {
15200e305d2STamas Berghammer         static ConstString g_remote_name("remote-android");
15300e305d2STamas Berghammer         return g_remote_name;
15400e305d2STamas Berghammer     }
1551c6a1ea9STamas Berghammer }
15600e305d2STamas Berghammer 
15700e305d2STamas Berghammer const char *
1581c6a1ea9STamas Berghammer PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
15900e305d2STamas Berghammer {
1601c6a1ea9STamas Berghammer     if (is_host)
1611c6a1ea9STamas Berghammer         return "Local Android user platform plug-in.";
1621c6a1ea9STamas Berghammer     else
16300e305d2STamas Berghammer         return "Remote Android user platform plug-in.";
16400e305d2STamas Berghammer }
16500e305d2STamas Berghammer 
16600e305d2STamas Berghammer lldb_private::ConstString
16700e305d2STamas Berghammer PlatformAndroid::GetPluginName()
16800e305d2STamas Berghammer {
1691c6a1ea9STamas Berghammer     return GetPluginNameStatic(IsHost());
17000e305d2STamas Berghammer }
17100e305d2STamas Berghammer 
17200e305d2STamas Berghammer Error
17300e305d2STamas Berghammer PlatformAndroid::ConnectRemote (Args& args)
17400e305d2STamas Berghammer {
175*6f001068SOleksiy Vyalov     m_device_id.clear ();
176*6f001068SOleksiy Vyalov 
1771c6a1ea9STamas Berghammer     if (IsHost())
1781c6a1ea9STamas Berghammer     {
1791c6a1ea9STamas Berghammer         return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
1801c6a1ea9STamas Berghammer     }
1811c6a1ea9STamas Berghammer 
18200e305d2STamas Berghammer     if (!m_remote_platform_sp)
18300e305d2STamas Berghammer         m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
184*6f001068SOleksiy Vyalov 
185*6f001068SOleksiy Vyalov     auto error = PlatformLinux::ConnectRemote (args);
186*6f001068SOleksiy Vyalov     if (error.Success ())
187*6f001068SOleksiy Vyalov     {
188*6f001068SOleksiy Vyalov         // Fetch the device list from ADB and if only 1 device found then use that device
189*6f001068SOleksiy Vyalov         // TODO: Handle the case when more device is available
190*6f001068SOleksiy Vyalov         AdbClient adb;
191*6f001068SOleksiy Vyalov         error = AdbClient::CreateByDeviceID (nullptr, adb);
192*6f001068SOleksiy Vyalov         if (error.Fail ())
193*6f001068SOleksiy Vyalov             return error;
194*6f001068SOleksiy Vyalov 
195*6f001068SOleksiy Vyalov         m_device_id = adb.GetDeviceID ();
196*6f001068SOleksiy Vyalov     }
197*6f001068SOleksiy Vyalov     return error;
198*6f001068SOleksiy Vyalov }
199*6f001068SOleksiy Vyalov 
200*6f001068SOleksiy Vyalov const char *
201*6f001068SOleksiy Vyalov PlatformAndroid::GetCacheHostname ()
202*6f001068SOleksiy Vyalov {
203*6f001068SOleksiy Vyalov     return m_device_id.c_str ();
20400e305d2STamas Berghammer }
205