File: installer.cc

package info (click to toggle)
android-platform-tools-base 2.2.2-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 113,928 kB
  • sloc: java: 696,396; xml: 45,920; cpp: 2,526; ansic: 1,432; sh: 508; lisp: 110; javascript: 108; makefile: 17
file content (135 lines) | stat: -rw-r--r-- 3,896 bytes parent folder | download | duplicates (3)
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
135
#include "installer.h"
#include <sstream>

#include "android_studio_version.h"
#include "bash_command.h"
#include "package_manager.h"
#include "profiler_file.h"
#include "utils/log.h"


using std::string;
using profiler::Log;

namespace profiler {
Installer::Installer(const char *app_package_name)
    : app_package_name_(app_package_name) {}

bool Installer::Install(const string &src_path, string *error_string) const {
  Log::I("Request to install sampler in app '%s\n'", app_package_name_.c_str());

  // Check if the sampler is already there.
  string dst_path;
  if (!GetInstallationPath(app_package_name_, &dst_path, error_string)) {
    error_string->append("Unable to generate installation path");
    return false;
  }

  ProfilerFile dst = ProfilerFile(dst_path);
  if (dst.Exists()) {
    Log::I("'%s' executable is already installed (found at '%s').\n",
        app_package_name_.c_str(), dst_path.c_str());
    return true;
  }

  Log::I("'%s' executable requires installation (missing from '%s').\n",
      app_package_name_.c_str(), dst_path.c_str());
  // We need to copy sampler to the app folder.

  ProfilerFile src(src_path);
  if (!src.Exists()) {
    *error_string = "Source does not exists (" + src_path + ").";
    return false;
  }

  if (!BashCommandRunner::IsRunAsCapable()) {
    *error_string = "System is not run-as capable";
    return false;
  }

  Log::I("Copying...\n");
  // sh -c \"cat /data/local/tmp/foo.so | run-as com.google.android.calendar sh
  // -c 'cat > foo.so ; chmod 700 foo.so'
  // TODO: Implement this in a clean way. With fork, execv and pipes?

  std::stringstream copy_command;
  copy_command << "sh -c \"";
  copy_command << "cat ";
  copy_command << src_path;
  copy_command << " | ";
  copy_command << "run-as ";
  copy_command << app_package_name_;
  copy_command << " sh -c 'cat > ";
  copy_command << dst_path;
  copy_command << "; chmod 700 ";
  copy_command << dst_path;
  copy_command << "'\"";
  BashCommandRunner cmd(copy_command.str());

  string out;
  bool success = cmd.Run("", &out);
  if (!success || !dst.Exists()) {
    *error_string = out;
    return false;
  }

  return true;
}

bool Installer::Uninstall(const string &binary_path,
                          string *error_string) const {
  ProfilerFile target(binary_path);
  if (!target.Exists()) {
    *error_string = "Cannot delete file '" + binary_path +
                    "': ProfilerFile does not exists.";
    return false;
  }
  BashCommandRunner rm("rm");
  string parameters;
  parameters.append(target.GetPath());
  bool success = rm.Run(parameters, error_string);
  if (!success || target.Exists()) {
    return false;
  }
  return true;
}

bool Installer::GetInstallationPath(const string &executable_path,
                                    string *install_path,
                                    string *error_string) const {
  string error_message;

  // Build the installation destination install_path:
  PackageManager pm;
  string app_base;
  bool ret = pm.GetAppDataPath(app_package_name_, &app_base, &error_message);
  if (!ret) {
    *error_string = error_message;
    return false;
  }

  ProfilerFile b(executable_path);
  string binary_filename = b.GetFileName();

  install_path->clear();
  install_path->append(app_base);
  install_path->append("/");
  install_path->append(GetBinaryNameForPackage(binary_filename));
  return true;
}

const string Installer::GetBinaryNameForPackage(
    const string &executable_filename) const {
  string binary_name;
  binary_name.append(executable_filename);
  binary_name.append("_for");
  binary_name.append("-");
  binary_name.append(this->app_package_name_);
  binary_name.append("-");
  binary_name.append("aarch64");  // TODO: Use "uname -m" instead or config
  // file.
  binary_name.append("-v");
  binary_name.append(kAndroidStudioVersion);
  return binary_name;
}
}  // namespace profiler