aboutsummaryrefslogtreecommitdiff
path: root/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
blob: bec9b40273787b720ea65b16eab8e5f152c2dfb6 (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
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.base;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;

import org.chromium.base.annotations.SuppressFBWarnings;

import java.io.File;

/**
 * Provides implementation of command line initialization for Android.
 */
public final class CommandLineInitUtil {

    private static final String TAG = "CommandLineInitUtil";

    /**
     * The location of the command line file needs to be in a protected
     * directory so requires root access to be tweaked, i.e., no other app in a
     * regular (non-rooted) device can change this file's contents.
     * See below for debugging on a regular (non-rooted) device.
     */
    private static final String COMMAND_LINE_FILE_PATH = "/data/local";

    /**
     * This path (writable by the shell in regular non-rooted "user" builds) is used when:
     * 1) The "debug app" is set to the application calling this.
     * and
     * 2) ADB is enabled.
     *
     */
    private static final String COMMAND_LINE_FILE_PATH_DEBUG_APP = "/data/local/tmp";

    private CommandLineInitUtil() {
    }

    /**
     * Initializes the CommandLine class, pulling command line arguments from {@code fileName}.
     * @param context  The {@link Context} to use to query whether or not this application is being
     *                 debugged, and whether or not the publicly writable command line file should
     *                 be used.
     * @param fileName The name of the command line file to pull arguments from.
     */
    @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
    public static void initCommandLine(Context context, String fileName) {
        if (!CommandLine.isInitialized()) {
            File commandLineFile = getAlternativeCommandLinePath(context, fileName);
            if (commandLineFile != null) {
                Log.i(TAG, "Using alternative command line file in " + commandLineFile.getPath());
            } else {
                commandLineFile = new File(COMMAND_LINE_FILE_PATH, fileName);
            }
            CommandLine.initFromFile(commandLineFile.getPath());
        }
    }

    /**
     * Use an alternative path if:
     * - The current build is "eng" or "userdebug", OR
     * - adb is enabled and this is the debug app.
     */
    @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME")
    private static File getAlternativeCommandLinePath(Context context, String fileName) {
        File alternativeCommandLineFile =
                new File(COMMAND_LINE_FILE_PATH_DEBUG_APP, fileName);
        if (!alternativeCommandLineFile.exists()) return null;
        try {
            if (BuildInfo.isDebugAndroid()) {
                return alternativeCommandLineFile;
            }

            String debugApp = Build.VERSION.SDK_INT < 17
                    ? getDebugAppPreJBMR1(context) : getDebugAppJBMR1(context);

            if (debugApp != null
                    && debugApp.equals(context.getApplicationContext().getPackageName())) {
                return alternativeCommandLineFile;
            }
        } catch (RuntimeException e) {
            Log.e(TAG, "Unable to detect alternative command line file");
        }

        return null;
    }

    @SuppressLint("NewApi")
    private static String getDebugAppJBMR1(Context context) {
        boolean adbEnabled = Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.ADB_ENABLED, 0) == 1;
        if (adbEnabled) {
            return Settings.Global.getString(context.getContentResolver(),
                    Settings.Global.DEBUG_APP);
        }
        return null;
    }

    @SuppressWarnings("deprecation")
    private static String getDebugAppPreJBMR1(Context context) {
        boolean adbEnabled = Settings.System.getInt(context.getContentResolver(),
                Settings.System.ADB_ENABLED, 0) == 1;
        if (adbEnabled) {
            return Settings.System.getString(context.getContentResolver(),
                    Settings.System.DEBUG_APP);
        }
        return null;
    }
}