termux-app

Форк
0
270 строк · 12.8 Кб
1
package com.termux.shared.android;
2

3
import android.annotation.SuppressLint;
4
import android.content.Context;
5
import android.content.pm.ApplicationInfo;
6
import android.content.pm.PackageInfo;
7
import android.os.Build;
8

9
import androidx.annotation.NonNull;
10

11
import com.google.common.base.Joiner;
12
import com.termux.shared.R;
13
import com.termux.shared.data.DataUtils;
14
import com.termux.shared.logger.Logger;
15
import com.termux.shared.markdown.MarkdownUtils;
16

17
import java.io.BufferedReader;
18
import java.io.IOException;
19
import java.io.InputStream;
20
import java.io.InputStreamReader;
21
import java.text.SimpleDateFormat;
22
import java.util.Date;
23
import java.util.Properties;
24
import java.util.TimeZone;
25
import java.util.regex.Matcher;
26
import java.util.regex.Pattern;
27

28
public class AndroidUtils {
29

30
    /**
31
     * Get a markdown {@link String} for the app info for the package associated with the {@code context}.
32
     * This will contain additional info about the app in addition to the one returned by
33
     * {@link #getAppInfoMarkdownString(Context, String)}, which will be got via the {@code context}
34
     * object.
35
     *
36
     * @param context The context for operations for the package.
37
     * @return Returns the markdown {@link String}.
38
     */
39
    public static String getAppInfoMarkdownString(@NonNull final Context context) {
40
        StringBuilder markdownString = new StringBuilder();
41

42
        String appInfo = getAppInfoMarkdownString(context, context.getPackageName());
43
        if (appInfo == null)
44
            return markdownString.toString();
45
        else
46
            markdownString.append(appInfo);
47

48
        String filesDir = context.getFilesDir().getAbsolutePath();
49
        if (!filesDir.equals("/data/user/0/" + context.getPackageName() + "/files") &&
50
            !filesDir.equals("/data/data/" + context.getPackageName() + "/files"))
51
            AndroidUtils.appendPropertyToMarkdown(markdownString,"FILES_DIR", filesDir);
52

53

54
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
55
            Long userId = PackageUtils.getUserIdForPackage(context);
56
            if (userId == null || userId != 0)
57
                AndroidUtils.appendPropertyToMarkdown(markdownString, "USER_ID", userId);
58
        }
59

60
        AndroidUtils.appendPropertyToMarkdownIfSet(markdownString,"PROFILE_OWNER", PackageUtils.getProfileOwnerPackageNameForUser(context));
61

62
        return markdownString.toString();
63
    }
64

65
    /**
66
     * Get a markdown {@link String} for the app info for the {@code packageName}.
67
     *
68
     * @param context The {@link Context} for operations.
69
     * @param packageName The package name of the package.
70
     * @return Returns the markdown {@link String}.
71
     */
72
    public static String getAppInfoMarkdownString(@NonNull final Context context, @NonNull final String packageName) {
73
        PackageInfo packageInfo = PackageUtils.getPackageInfoForPackage(context, packageName);
74
        if (packageInfo == null) return null;
75
        ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoForPackage(context, packageName);
76
        if (applicationInfo == null) return null;
77

78
        StringBuilder markdownString = new StringBuilder();
79

80
        AndroidUtils.appendPropertyToMarkdown(markdownString,"APP_NAME", PackageUtils.getAppNameForPackage(context, applicationInfo));
81
        AndroidUtils.appendPropertyToMarkdown(markdownString,"PACKAGE_NAME", PackageUtils.getPackageNameForPackage(applicationInfo));
82
        AndroidUtils.appendPropertyToMarkdown(markdownString,"VERSION_NAME", PackageUtils.getVersionNameForPackage(packageInfo));
83
        AndroidUtils.appendPropertyToMarkdown(markdownString,"VERSION_CODE", PackageUtils.getVersionCodeForPackage(packageInfo));
84
        AndroidUtils.appendPropertyToMarkdown(markdownString,"UID", PackageUtils.getUidForPackage(applicationInfo));
85
        AndroidUtils.appendPropertyToMarkdown(markdownString,"TARGET_SDK", PackageUtils.getTargetSDKForPackage(applicationInfo));
86
        AndroidUtils.appendPropertyToMarkdown(markdownString,"IS_DEBUGGABLE_BUILD", PackageUtils.isAppForPackageADebuggableBuild(applicationInfo));
87

88
        if (PackageUtils.isAppInstalledOnExternalStorage(applicationInfo)) {
89
            AndroidUtils.appendPropertyToMarkdown(markdownString,"APK_PATH", PackageUtils.getBaseAPKPathForPackage(applicationInfo));
90
            AndroidUtils.appendPropertyToMarkdown(markdownString,"IS_INSTALLED_ON_EXTERNAL_STORAGE", true);
91
        }
92

93
        AndroidUtils.appendPropertyToMarkdown(markdownString,"SE_PROCESS_CONTEXT", SELinuxUtils.getContext());
94
        AndroidUtils.appendPropertyToMarkdown(markdownString,"SE_FILE_CONTEXT", SELinuxUtils.getFileContext(context.getFilesDir().getAbsolutePath()));
95

96
        String seInfoUser = PackageUtils.getApplicationInfoSeInfoUserForPackage(applicationInfo);
97
        AndroidUtils.appendPropertyToMarkdown(markdownString,"SE_INFO", PackageUtils.getApplicationInfoSeInfoForPackage(applicationInfo) +
98
            (DataUtils.isNullOrEmpty(seInfoUser) ? "" : seInfoUser));
99

100
        return markdownString.toString();
101
    }
102

103
    public static String getDeviceInfoMarkdownString(@NonNull final Context context) {
104
        return getDeviceInfoMarkdownString(context, false);
105
    }
106

107
    /**
108
     * Get a markdown {@link String} for the device info.
109
     *
110
     * @param context The context for operations.
111
     * @param addPhantomProcessesInfo If phantom processes info should be added on Android >= 12.
112
     * @return Returns the markdown {@link String}.
113
     */
114
    public static String getDeviceInfoMarkdownString(@NonNull final Context context, boolean addPhantomProcessesInfo) {
115
        // Some properties cannot be read with {@link System#getProperty(String)} but can be read
116
        // directly by running getprop command
117
        Properties systemProperties = getSystemProperties();
118

119
        StringBuilder markdownString = new StringBuilder();
120

121
        markdownString.append("## Device Info");
122

123
        markdownString.append("\n\n### Software\n");
124
        appendPropertyToMarkdown(markdownString,"OS_VERSION", getSystemPropertyWithAndroidAPI("os.version"));
125
        appendPropertyToMarkdown(markdownString, "SDK_INT", Build.VERSION.SDK_INT);
126
        // If its a release version
127
        if ("REL".equals(Build.VERSION.CODENAME))
128
            appendPropertyToMarkdown(markdownString, "RELEASE", Build.VERSION.RELEASE);
129
        else
130
            appendPropertyToMarkdown(markdownString, "CODENAME", Build.VERSION.CODENAME);
131
        appendPropertyToMarkdown(markdownString, "ID", Build.ID);
132
        appendPropertyToMarkdown(markdownString, "DISPLAY", Build.DISPLAY);
133
        appendPropertyToMarkdown(markdownString, "INCREMENTAL", Build.VERSION.INCREMENTAL);
134
        appendPropertyToMarkdownIfSet(markdownString, "SECURITY_PATCH", systemProperties.getProperty("ro.build.version.security_patch"));
135
        appendPropertyToMarkdownIfSet(markdownString, "IS_DEBUGGABLE", systemProperties.getProperty("ro.debuggable"));
136
        appendPropertyToMarkdownIfSet(markdownString, "IS_EMULATOR", systemProperties.getProperty("ro.boot.qemu"));
137
        appendPropertyToMarkdownIfSet(markdownString, "IS_TREBLE_ENABLED", systemProperties.getProperty("ro.treble.enabled"));
138
        appendPropertyToMarkdown(markdownString, "TYPE", Build.TYPE);
139
        appendPropertyToMarkdown(markdownString, "TAGS", Build.TAGS);
140

141
        // If on Android >= 12
142
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
143
            Integer maxPhantomProcesses = PhantomProcessUtils.getActivityManagerMaxPhantomProcesses(context);
144
            if (maxPhantomProcesses != null)
145
                appendPropertyToMarkdown(markdownString, "MAX_PHANTOM_PROCESSES", maxPhantomProcesses);
146
            else
147
                appendLiteralPropertyToMarkdown(markdownString, "MAX_PHANTOM_PROCESSES", "- (*" + context.getString(R.string.msg_requires_dump_and_package_usage_stats_permissions) + "*)");
148

149
            appendPropertyToMarkdown(markdownString, "MONITOR_PHANTOM_PROCS", PhantomProcessUtils.getFeatureFlagMonitorPhantomProcsValueString(context).getName());
150
            appendPropertyToMarkdown(markdownString, "DEVICE_CONFIG_SYNC_DISABLED", PhantomProcessUtils.getSettingsGlobalDeviceConfigSyncDisabled(context));
151
        }
152

153
        markdownString.append("\n\n### Hardware\n");
154
        appendPropertyToMarkdown(markdownString, "MANUFACTURER", Build.MANUFACTURER);
155
        appendPropertyToMarkdown(markdownString, "BRAND", Build.BRAND);
156
        appendPropertyToMarkdown(markdownString, "MODEL", Build.MODEL);
157
        appendPropertyToMarkdown(markdownString, "PRODUCT", Build.PRODUCT);
158
        appendPropertyToMarkdown(markdownString, "BOARD", Build.BOARD);
159
        appendPropertyToMarkdown(markdownString, "HARDWARE", Build.HARDWARE);
160
        appendPropertyToMarkdown(markdownString, "DEVICE", Build.DEVICE);
161
        appendPropertyToMarkdown(markdownString, "SUPPORTED_ABIS", Joiner.on(", ").skipNulls().join(Build.SUPPORTED_ABIS));
162

163
        markdownString.append("\n##\n");
164

165
        return markdownString.toString();
166
    }
167

168

169

170
    public static Properties getSystemProperties() {
171
        Properties systemProperties = new Properties();
172

173
        // getprop commands returns values in the format `[key]: [value]`
174
        // Regex matches string starting with a literal `[`,
175
        // followed by one or more characters that do not match a closing square bracket as the key,
176
        // followed by a literal `]: [`,
177
        // followed by one or more characters as the value,
178
        // followed by string ending with literal `]`
179
        // multiline values will be ignored
180
        Pattern propertiesPattern = Pattern.compile("^\\[([^]]+)]: \\[(.+)]$");
181

182
        try {
183
            Process process = new ProcessBuilder()
184
                .command("/system/bin/getprop")
185
                .redirectErrorStream(true)
186
                .start();
187

188
            InputStream inputStream = process.getInputStream();
189
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
190
            String line, key, value;
191

192
            while ((line = bufferedReader.readLine()) != null) {
193
                Matcher matcher = propertiesPattern.matcher(line);
194
                if (matcher.matches()) {
195
                    key = matcher.group(1);
196
                    value = matcher.group(2);
197
                    if (key != null && value != null && !key.isEmpty() && !value.isEmpty())
198
                        systemProperties.put(key, value);
199
                }
200
            }
201

202
            bufferedReader.close();
203
            process.destroy();
204

205
        } catch (IOException e) {
206
            Logger.logStackTraceWithMessage("Failed to get run \"/system/bin/getprop\" to get system properties.", e);
207
        }
208

209
        //for (String key : systemProperties.stringPropertyNames()) {
210
        //    Logger.logVerbose(key + ": " +  systemProperties.get(key));
211
        //}
212

213
        return systemProperties;
214
    }
215

216
    public static String getSystemPropertyWithAndroidAPI(@NonNull String property) {
217
        try {
218
            return System.getProperty(property);
219
        } catch (Exception e) {
220
            Logger.logVerbose("Failed to get system property \"" + property + "\":" + e.getMessage());
221
            return null;
222
        }
223
    }
224

225
    public static void appendPropertyToMarkdownIfSet(StringBuilder markdownString, String label, Object value) {
226
        if (value == null) return;
227
        if (value instanceof String && (((String) value).isEmpty()) || "REL".equals(value)) return;
228
        markdownString.append("\n").append(getPropertyMarkdown(label, value));
229
    }
230

231
    public static void appendPropertyToMarkdown(StringBuilder markdownString, String label, Object value) {
232
        markdownString.append("\n").append(getPropertyMarkdown(label, value));
233
    }
234

235
    public static String getPropertyMarkdown(String label, Object value) {
236
        return MarkdownUtils.getSingleLineMarkdownStringEntry(label, value, "-");
237
    }
238

239
    public static void appendLiteralPropertyToMarkdown(StringBuilder markdownString, String label, Object value) {
240
        markdownString.append("\n").append(getLiteralPropertyMarkdown(label, value));
241
    }
242

243
    public static String getLiteralPropertyMarkdown(String label, Object value) {
244
        return MarkdownUtils.getLiteralSingleLineMarkdownStringEntry(label, value, "-");
245
    }
246

247

248

249
    public static String getCurrentTimeStamp() {
250
        @SuppressLint("SimpleDateFormat")
251
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
252
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
253
        return df.format(new Date());
254
    }
255

256
    public static String getCurrentMilliSecondUTCTimeStamp() {
257
        @SuppressLint("SimpleDateFormat")
258
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
259
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
260
        return df.format(new Date());
261
    }
262

263
    public static String getCurrentMilliSecondLocalTimeStamp() {
264
        @SuppressLint("SimpleDateFormat")
265
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss.SSS");
266
        df.setTimeZone(TimeZone.getDefault());
267
        return df.format(new Date());
268
    }
269

270
}
271

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.