1 //===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Host/HostInfo.h"
16 
17 // Project includes
18 #include "AdbClient.h"
19 #include "PlatformAndroid.h"
20 #include "PlatformAndroidRemoteGDBServer.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::platform_android;
25 
26 static uint32_t g_initialize_count = 0;
27 
28 void
29 PlatformAndroid::Initialize ()
30 {
31     PlatformLinux::Initialize ();
32 
33     if (g_initialize_count++ == 0)
34     {
35 #if defined(__ANDROID__)
36         PlatformSP default_platform_sp (new PlatformAndroid(true));
37         default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
38         Platform::SetHostPlatform (default_platform_sp);
39 #endif
40         PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
41                                        PlatformAndroid::GetPluginDescriptionStatic(false),
42                                        PlatformAndroid::CreateInstance);
43     }
44 }
45 
46 void
47 PlatformAndroid::Terminate ()
48 {
49     if (g_initialize_count > 0)
50     {
51         if (--g_initialize_count == 0)
52         {
53             PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
54         }
55     }
56 
57     PlatformLinux::Terminate ();
58 }
59 
60 PlatformSP
61 PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
62 {
63     Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
64     if (log)
65     {
66         const char *arch_name;
67         if (arch && arch->GetArchitectureName ())
68             arch_name = arch->GetArchitectureName ();
69         else
70             arch_name = "<null>";
71 
72         const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
73 
74         log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
75     }
76 
77     bool create = force;
78     if (create == false && arch && arch->IsValid())
79     {
80         const llvm::Triple &triple = arch->GetTriple();
81         switch (triple.getVendor())
82         {
83             case llvm::Triple::PC:
84                 create = true;
85                 break;
86 
87 #if defined(__ANDROID__)
88             // Only accept "unknown" for the vendor if the host is android and
89             // it "unknown" wasn't specified (it was just returned because it
90             // was NOT specified_
91             case llvm::Triple::VendorType::UnknownVendor:
92                 create = !arch->TripleVendorWasSpecified();
93                 break;
94 #endif
95             default:
96                 break;
97         }
98 
99         if (create)
100         {
101             switch (triple.getOS())
102             {
103                 case llvm::Triple::Android:
104                     break;
105 
106 #if defined(__ANDROID__)
107                 // Only accept "unknown" for the OS if the host is android and
108                 // it "unknown" wasn't specified (it was just returned because it
109                 // was NOT specified)
110                 case llvm::Triple::OSType::UnknownOS:
111                     create = !arch->TripleOSWasSpecified();
112                     break;
113 #endif
114                 default:
115                     create = false;
116                     break;
117             }
118         }
119     }
120 
121     if (create)
122     {
123         if (log)
124             log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
125         return PlatformSP(new PlatformAndroid(false));
126     }
127 
128     if (log)
129         log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);
130 
131     return PlatformSP();
132 }
133 
134 PlatformAndroid::PlatformAndroid (bool is_host) :
135     PlatformLinux(is_host)
136 {
137 }
138 
139 PlatformAndroid::~PlatformAndroid()
140 {
141 }
142 
143 ConstString
144 PlatformAndroid::GetPluginNameStatic (bool is_host)
145 {
146     if (is_host)
147     {
148         static ConstString g_host_name(Platform::GetHostPlatformName ());
149         return g_host_name;
150     }
151     else
152     {
153         static ConstString g_remote_name("remote-android");
154         return g_remote_name;
155     }
156 }
157 
158 const char *
159 PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
160 {
161     if (is_host)
162         return "Local Android user platform plug-in.";
163     else
164         return "Remote Android user platform plug-in.";
165 }
166 
167 ConstString
168 PlatformAndroid::GetPluginName()
169 {
170     return GetPluginNameStatic(IsHost());
171 }
172 
173 Error
174 PlatformAndroid::ConnectRemote (Args& args)
175 {
176     m_device_id.clear ();
177 
178     if (IsHost())
179     {
180         return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
181     }
182 
183     if (!m_remote_platform_sp)
184         m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
185 
186     auto error = PlatformLinux::ConnectRemote (args);
187     if (error.Success ())
188     {
189         // Fetch the device list from ADB and if only 1 device found then use that device
190         // TODO: Handle the case when more device is available
191         AdbClient adb;
192         error = AdbClient::CreateByDeviceID (nullptr, adb);
193         if (error.Fail ())
194             return error;
195 
196         m_device_id = adb.GetDeviceID ();
197     }
198     return error;
199 }
200 
201 const char *
202 PlatformAndroid::GetCacheHostname ()
203 {
204     return m_device_id.c_str ();
205 }
206