1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi.aware;
18 
19 import android.os.Binder;
20 import android.os.ShellCommand;
21 import android.text.TextUtils;
22 import android.util.Log;
23 
24 import java.io.PrintWriter;
25 import java.util.HashMap;
26 import java.util.Map;
27 
28 /**
29  * Interprets and executes 'adb shell cmd wifiaware [args]'.
30  */
31 public class WifiAwareShellCommand extends ShellCommand {
32     private static final String TAG = "WifiAwareShellCommand";
33 
34     private Map<String, DelegatedShellCommand> mDelegatedCommands = new HashMap<>();
35 
36     /**
37      * Register an delegated command interpreter for the specified 'command'. Each class can
38      * interpret and execute their own commands.
39      */
register(String command, DelegatedShellCommand shellCommand)40     public void register(String command, DelegatedShellCommand shellCommand) {
41         if (mDelegatedCommands.containsKey(command)) {
42             Log.e(TAG, "register: overwriting existing command -- '" + command + "'");
43         }
44 
45         mDelegatedCommands.put(command, shellCommand);
46     }
47 
48     @Override
onCommand(String cmd)49     public int onCommand(String cmd) {
50         checkRootPermission();
51 
52         final PrintWriter pw = getErrPrintWriter();
53         try {
54             if ("reset".equals(cmd)) {
55                 for (DelegatedShellCommand dsc: mDelegatedCommands.values()) {
56                     dsc.onReset();
57                 }
58                 return 0;
59             } else {
60                 DelegatedShellCommand delegatedCmd = null;
61                 if (!TextUtils.isEmpty(cmd)) {
62                     delegatedCmd = mDelegatedCommands.get(cmd);
63                 }
64 
65                 if (delegatedCmd != null) {
66                     return delegatedCmd.onCommand(this);
67                 } else {
68                     return handleDefaultCommands(cmd);
69                 }
70             }
71         } catch (Exception e) {
72             pw.println("Exception: " + e);
73         }
74         return -1;
75     }
76 
checkRootPermission()77     private void checkRootPermission() {
78         final int uid = Binder.getCallingUid();
79         if (uid == 0) {
80             // Root can do anything.
81             return;
82         }
83         throw new SecurityException("Uid " + uid + " does not have access to wifiaware commands");
84     }
85 
86     @Override
onHelp()87     public void onHelp() {
88         final PrintWriter pw = getOutPrintWriter();
89 
90         pw.println("Wi-Fi Aware (wifiaware) commands:");
91         pw.println("  help");
92         pw.println("    Print this help text.");
93         pw.println("  reset");
94         pw.println("    Reset parameters to default values.");
95         for (Map.Entry<String, DelegatedShellCommand> sce: mDelegatedCommands.entrySet()) {
96             sce.getValue().onHelp(sce.getKey(), this);
97         }
98         pw.println();
99     }
100 
101     /**
102      * Interface that delegated command targets must implement. They are passed the parent shell
103      * command (the real command interpreter) from which they can obtain arguments.
104      */
105     public interface DelegatedShellCommand {
106         /**
107          * Execute the specified command. Use the parent shell to obtain arguments. Note that the
108          * first argument (which specified the delegated shell) has already been extracted.
109          */
onCommand(ShellCommand parentShell)110         int onCommand(ShellCommand parentShell);
111 
112         /**
113          * Reset all parameters to their default values.
114          */
onReset()115         void onReset();
116 
117         /**
118          * Print out help for the delegated command. The name of the delegated command is passed
119          * as a first argument as an assist (prevents hard-coding of that string in multiple
120          * places).
121          */
onHelp(String command, ShellCommand parentShell)122         void onHelp(String command, ShellCommand parentShell);
123 
124     }
125 }
126