• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.android.documentsui.queries;
17 
18 import static com.android.documentsui.base.Shared.DEBUG;
19 
20 import android.content.Context;
21 import android.support.annotation.VisibleForTesting;
22 import android.text.TextUtils;
23 import android.util.Log;
24 
25 import com.android.documentsui.DocumentsApplication;
26 import com.android.documentsui.R;
27 import com.android.documentsui.base.DebugFlags;
28 import com.android.documentsui.base.EventHandler;
29 import com.android.documentsui.base.Features;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 public final class CommandInterceptor implements EventHandler<String> {
35 
36     @VisibleForTesting
37     static final String COMMAND_PREFIX = ":";
38 
39     private static final String TAG = "CommandInterceptor";
40 
41     private final List<EventHandler<String[]>> mCommands = new ArrayList<>();
42 
43     private Features mFeatures;
44 
CommandInterceptor(Features features)45     public CommandInterceptor(Features features) {
46         mFeatures = features;
47 
48         mCommands.add(this::quickViewer);
49         mCommands.add(this::gestureScale);
50         mCommands.add(this::archiveCreation);
51         mCommands.add(this::docDetails);
52         mCommands.add(this::forcePaging);
53     }
54 
add(EventHandler<String[]> handler)55     public void add(EventHandler<String[]> handler) {
56         mCommands.add(handler);
57     }
58 
59     @Override
accept(String query)60     public boolean accept(String query) {
61         if (!mFeatures.isCommandInterceptorEnabled()) {
62             if (DEBUG) Log.v(TAG, "Skipping input, command interceptor disabled.");
63             return false;
64         }
65 
66         if (query.length() > COMMAND_PREFIX.length() && query.startsWith(COMMAND_PREFIX)) {
67             String[] tokens = query.substring(COMMAND_PREFIX.length()).split("\\s+");
68             for (EventHandler<String[]> command : mCommands) {
69                 if (command.accept(tokens)) {
70                     return true;
71                 }
72             }
73             Log.d(TAG, "Unrecognized debug command: " + query);
74         }
75         return false;
76     }
77 
quickViewer(String[] tokens)78     private boolean quickViewer(String[] tokens) {
79         if ("qv".equals(tokens[0])) {
80             if (tokens.length == 2 && !TextUtils.isEmpty(tokens[1])) {
81                 DebugFlags.setQuickViewer(tokens[1]);
82                 Log.i(TAG, "Set quick viewer to: " + tokens[1]);
83                 return true;
84             } else {
85                 Log.w(TAG, "Invalid command structure: " + TextUtils.join(" ", tokens));
86             }
87         } else if ("deqv".equals(tokens[0])) {
88             Log.i(TAG, "Unset quick viewer");
89             DebugFlags.setQuickViewer(null);
90             return true;
91         }
92         return false;
93     }
94 
gestureScale(String[] tokens)95     private boolean gestureScale(String[] tokens) {
96         if ("gs".equals(tokens[0])) {
97             if (tokens.length == 2 && !TextUtils.isEmpty(tokens[1])) {
98                 boolean enabled = asBool(tokens[1]);
99                 mFeatures.forceFeature(R.bool.feature_gesture_scale, enabled);
100                 Log.i(TAG, "Set gesture scale enabled to: " + enabled);
101                 return true;
102             }
103             Log.w(TAG, "Invalid command structure: " + TextUtils.join(" ", tokens));
104         }
105         return false;
106     }
107 
archiveCreation(String[] tokens)108     private boolean archiveCreation(String[] tokens) {
109         if ("zip".equals(tokens[0])) {
110             if (tokens.length == 2 && !TextUtils.isEmpty(tokens[1])) {
111                 boolean enabled = asBool(tokens[1]);
112                 mFeatures.forceFeature(R.bool.feature_archive_creation, enabled);
113                 Log.i(TAG, "Set gesture scale enabled to: " + enabled);
114                 return true;
115             }
116             Log.w(TAG, "Invalid command structure: " + TextUtils.join(" ", tokens));
117         }
118         return false;
119     }
120 
docDetails(String[] tokens)121     private boolean docDetails(String[] tokens) {
122         if ("docinfo".equals(tokens[0])) {
123             if (tokens.length == 2 && !TextUtils.isEmpty(tokens[1])) {
124                 boolean enabled = asBool(tokens[1]);
125                 DebugFlags.setDocumentDetailsEnabled(enabled);
126                 Log.i(TAG, "Set gesture scale enabled to: " + enabled);
127                 return true;
128             }
129             Log.w(TAG, "Invalid command structure: " + TextUtils.join(" ", tokens));
130         }
131         return false;
132     }
133 
forcePaging(String[] tokens)134     private boolean forcePaging(String[] tokens) {
135         if ("page".equals(tokens[0])) {
136             if (tokens.length >= 2) {
137                 try {
138                     int offset = Integer.parseInt(tokens[1]);
139                     int limit = (tokens.length == 3) ? Integer.parseInt(tokens[2]) : -1;
140                     DebugFlags.setForcedPaging(offset, limit);
141                     Log.i(TAG, "Set forced paging to offset: " + offset + ", limit: " + limit);
142                     return true;
143                 } catch (NumberFormatException e) {
144                     Log.w(TAG, "Command input does not contain valid numbers: "
145                             + TextUtils.join(" ", tokens));
146                     return false;
147                 }
148             } else {
149                 Log.w(TAG, "Invalid command structure: " + TextUtils.join(" ", tokens));
150             }
151         } else if ("deqv".equals(tokens[0])) {
152             Log.i(TAG, "Unset quick viewer");
153             DebugFlags.setQuickViewer(null);
154             return true;
155         }
156         return false;
157     }
158 
asBool(String val)159     private final boolean asBool(String val) {
160         if (val == null || val.equals("0")) {
161             return false;
162         }
163         if (val.equals("1")) {
164             return true;
165         }
166         return Boolean.valueOf(val);
167     }
168 
169     public static final class DumpRootsCacheHandler implements EventHandler<String[]> {
170         private final Context mContext;
171 
DumpRootsCacheHandler(Context context)172         public DumpRootsCacheHandler(Context context) {
173             mContext = context;
174         }
175 
176         @Override
accept(String[] tokens)177         public boolean accept(String[] tokens) {
178             if ("dumpCache".equals(tokens[0])) {
179                 DocumentsApplication.getProvidersCache(mContext).logCache();
180                 return true;
181             }
182             return false;
183         }
184     }
185 }
186