• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.base;
6 
7 import android.content.Context;
8 import android.provider.Settings;
9 
10 import androidx.annotation.Nullable;
11 
12 import org.chromium.base.supplier.Supplier;
13 
14 import java.io.File;
15 
16 /** Provides implementation of command line initialization for Android. */
17 public final class CommandLineInitUtil {
18     /**
19      * The location of the command line file needs to be in a protected
20      * directory so requires root access to be tweaked, i.e., no other app in a
21      * regular (non-rooted) device can change this file's contents.
22      * See below for debugging on a regular (non-rooted) device.
23      */
24     private static final String COMMAND_LINE_FILE_PATH = "/data/local";
25 
26     /**
27      * This path (writable by the shell in regular non-rooted "user" builds) is used when:
28      * 1) The "debug app" is set to the application calling this.
29      * and
30      * 2) ADB is enabled.
31      * 3) Force enabled by the embedder.
32      */
33     private static final String COMMAND_LINE_FILE_PATH_DEBUG_APP = "/data/local/tmp";
34 
35     /** The name of the command line file to pull arguments from. */
36     private static String sFilenameOverrideForTesting;
37 
CommandLineInitUtil()38     private CommandLineInitUtil() {}
39 
40     /** Set the filename to use. */
setFilenameOverrideForTesting(String value)41     public static void setFilenameOverrideForTesting(String value) {
42         sFilenameOverrideForTesting = value;
43     }
44 
45     /**
46      * Initializes the CommandLine class, pulling command line arguments from {@code fileName}.
47      * @param fileName The name of the command line file to pull arguments from.
48      */
initCommandLine(String fileName)49     public static void initCommandLine(String fileName) {
50         initCommandLine(fileName, null);
51     }
52 
53     /**
54      * Initializes the CommandLine class, pulling command line arguments from {@code fileName}.
55      * @param fileName The name of the command line file to pull arguments from.
56      * @param shouldUseDebugFlags If non-null, returns whether debug flags are allowed to be used.
57      */
initCommandLine( String fileName, @Nullable Supplier<Boolean> shouldUseDebugFlags)58     public static void initCommandLine(
59             String fileName, @Nullable Supplier<Boolean> shouldUseDebugFlags) {
60         if (sFilenameOverrideForTesting != null) {
61             fileName = sFilenameOverrideForTesting;
62         }
63         assert !CommandLine.isInitialized();
64         File commandLineFile = new File(COMMAND_LINE_FILE_PATH_DEBUG_APP, fileName);
65         // shouldUseDebugCommandLine() uses IPC, so don't bother calling it if no flags file exists.
66         boolean debugFlagsExist = commandLineFile.exists();
67         if (!debugFlagsExist || !shouldUseDebugCommandLine(shouldUseDebugFlags)) {
68             commandLineFile = new File(COMMAND_LINE_FILE_PATH, fileName);
69         }
70         CommandLine.initFromFile(commandLineFile.getPath());
71     }
72 
73     /**
74      * Use an alternative path if:
75      * - The current build is "eng" or "userdebug", OR
76      * - adb is enabled and this is the debug app, OR
77      * - Force enabled by the embedder.
78      * @param shouldUseDebugFlags If non-null, returns whether debug flags are allowed to be used.
79      */
shouldUseDebugCommandLine( @ullable Supplier<Boolean> shouldUseDebugFlags)80     private static boolean shouldUseDebugCommandLine(
81             @Nullable Supplier<Boolean> shouldUseDebugFlags) {
82         if (shouldUseDebugFlags != null && shouldUseDebugFlags.get()) return true;
83         Context context = ContextUtils.getApplicationContext();
84         // Check isDebugAndroid() last to get full code coverage when using userdebug devices.
85         return context.getPackageName().equals(getDebugApp(context)) || BuildInfo.isDebugAndroid();
86     }
87 
getDebugApp(Context context)88     private static String getDebugApp(Context context) {
89         boolean adbEnabled =
90                 Settings.Global.getInt(context.getContentResolver(), Settings.Global.ADB_ENABLED, 0)
91                         == 1;
92         if (adbEnabled) {
93             return Settings.Global.getString(
94                     context.getContentResolver(), Settings.Global.DEBUG_APP);
95         }
96         return null;
97     }
98 }
99