Loading src/com/android/documentsui/BaseActivity.java +12 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.Injector.Injected; import com.android.documentsui.NavigationViewManager.Breadcrumb; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; Loading Loading @@ -178,9 +179,17 @@ public abstract class BaseActivity // We piggy back on search input as it is the only text input // area in the app. But the functionality is independent // of "regular" search query processing. CommandInterceptor dbgCommands = new CommandInterceptor(mInjector.features); dbgCommands.add(new CommandInterceptor.DumpRootsCacheHandler(this)); mSearchManager = new SearchViewManager(searchListener, dbgCommands, icicle); final CommandInterceptor cmdInterceptor = new CommandInterceptor(mInjector.features); cmdInterceptor.add(new CommandInterceptor.DumpRootsCacheHandler(this)); // A tiny decorator that adds support for enabling CommandInterceptor // based on query input. It's sorta like CommandInterceptor, but its metaaahhh. EventHandler<String> queryInterceptor = CommandInterceptor.createDebugModeFlipper( mInjector.features, mInjector.debugHelper::toggleDebugMode, cmdInterceptor); mSearchManager = new SearchViewManager(searchListener, queryInterceptor, icicle); mSortController = SortController.create(this, mState.derivedMode, mState.sortModel); mPreferencesMonitor = new PreferencesMonitor( Loading src/com/android/documentsui/base/DebugHelper.java +47 −37 Original line number Diff line number Diff line Loading @@ -26,29 +26,35 @@ import com.android.documentsui.R; * Debug menu tools requested by QA Fred. */ public class DebugHelper { private static final String TAG = "DebugHelper"; private static final int[][] code = new int[][] { private static final int[][] sCode = new int[][] { {19, 19, 20, 20, 21, 22, 21, 22, 30, 29}, {51, 51, 47, 47, 29, 32, 29, 32, 30, 29} }; private static final int[][] colors = new int[][] { private static final int[][] sColors = new int[][] { {0xFFDB3236, 0xFFB71C1C}, {0xFF3cba54, 0xFF1B5E20}, {0xFFf4c20d, 0xFFF9A825}, {0xFF4885ed, 0xFF0D47A1} }; private static final Pair[] messages = new Pair[]{ @SuppressWarnings("unchecked") private static final Pair<String, Integer>[] sMessages = new Pair[]{ new Pair<>("Woof Woof", R.drawable.debug_msg_1), new Pair<>("ワンワン", R.drawable.debug_msg_2) }; private boolean debugEnabled = false; private long lastTime = 0; private int position = 0; private int codeIndex = 0; private int colorIndex = 0; private int messageIndex = 0; private Injector<?> mInjector; private final Injector<?> mInjector; private boolean mDebugEnabled; private long mLastTime; private int mPosition; private int mCodeIndex; private int mColorIndex; private int mMessageIndex; public DebugHelper(Injector<?> injector) { mInjector = injector; Loading @@ -57,56 +63,60 @@ public class DebugHelper { public int[] getNextColors() { assert (mInjector.features.isDebugSupportEnabled()); if (colorIndex == colors.length) { colorIndex = 0; if (mColorIndex == sColors.length) { mColorIndex = 0; } return colors[colorIndex++]; return sColors[mColorIndex++]; } public Pair<String, Integer> getNextMessage() { assert (mInjector.features.isDebugSupportEnabled()); if (messageIndex == messages.length) { messageIndex = 0; if (mMessageIndex == sMessages.length) { mMessageIndex = 0; } return messages[messageIndex++]; return sMessages[mMessageIndex++]; } public void debugCheck(long time, int keyCode) { if (time == lastTime) { if (time == mLastTime) { return; } lastTime = time; mLastTime = time; if (position == 0) { for (int i = 0; i < code.length; i++) { if (keyCode == code[i][0]) { codeIndex = i; if (mPosition == 0) { for (int i = 0; i < sCode.length; i++) { if (keyCode == sCode[i][0]) { mCodeIndex = i; break; } } } if (keyCode == code[codeIndex][position]) { position++; } else if (position > 2 || (position == 2 && keyCode != code[codeIndex][0])) { position = 0; if (keyCode == sCode[mCodeIndex][mPosition]) { mPosition++; } else if (mPosition > 2 || (mPosition == 2 && keyCode != sCode[mCodeIndex][0])) { mPosition = 0; } if (position == code[codeIndex].length) { position = 0; debugEnabled = !debugEnabled; if (mPosition == sCode[mCodeIndex].length) { mPosition = 0; toggleDebugMode(); } } public void toggleDebugMode() { mDebugEnabled = !mDebugEnabled; // Actions is content-scope, so it can technically be null, though // not likely. if (mInjector.actions != null) { mInjector.actions.setDebugMode(debugEnabled); mInjector.actions.setDebugMode(mDebugEnabled); } if (Shared.VERBOSE) { Log.v(TAG, "Debug mode " + (debugEnabled ? "on" : "off")); } Log.v(TAG, "Debug mode " + (mDebugEnabled ? "on" : "off")); } } } src/com/android/documentsui/base/Features.java +11 −4 Original line number Diff line number Diff line Loading @@ -90,8 +90,8 @@ public interface Features { @Override public boolean isCommandInterceptorEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES) && isEnabled(R.bool.feature_command_interceptor); assert(isDebugPolicyEnabled()); return isEnabled(R.bool.feature_command_interceptor); } @Override Loading @@ -104,10 +104,13 @@ public interface Features { return isEnabled(R.bool.feature_content_refresh); } private boolean isDebugPolicyEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES); } @Override public boolean isDebugSupportEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES) && !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN); return isDebugPolicyEnabled() && isFunPolicyEnabled(); } @Override Loading @@ -115,6 +118,10 @@ public interface Features { return isEnabled(R.bool.feature_folders_in_search_results); } private boolean isFunPolicyEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN); } @Override public boolean isGestureScaleEnabled() { return isEnabled(R.bool.feature_gesture_scale); Loading src/com/android/documentsui/queries/CommandInterceptor.java +35 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public final class CommandInterceptor implements EventHandler<String> { @Override public boolean accept(String query) { if (!mFeatures.isDebugSupportEnabled()) { return false; } if (!mFeatures.isCommandInterceptorEnabled()) { if (DEBUG) Log.v(TAG, "Skipping input, command interceptor disabled."); return false; Loading Loading @@ -196,4 +200,35 @@ public final class CommandInterceptor implements EventHandler<String> { return false; } } /** * Wraps {@link CommandInterceptor} in a tiny decorator that adds support for * enabling CommandInterceptor feature based on some magic query input. * * <p>It's like super meta, maaaannn. */ public static final EventHandler<String> createDebugModeFlipper( Features features, Runnable debugFlipper, CommandInterceptor interceptor) { if (!features.isDebugSupportEnabled()) { return interceptor; } String magicString1 = COMMAND_PREFIX + "wwssadadba"; String magicString2 = "up up down down left right left right b a"; return new EventHandler<String>() { @Override public boolean accept(String query) { assert(features.isDebugSupportEnabled()); if (magicString1.equals(query) || magicString2.equals(query)) { debugFlipper.run(); } return interceptor.accept(query); } }; } } src/com/android/documentsui/queries/SearchViewManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.widget.SearchView.OnQueryTextListener; import com.android.documentsui.R; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; Loading @@ -48,7 +49,7 @@ public class SearchViewManager implements private static final String TAG = "SearchManager"; private final SearchManagerListener mListener; private final CommandInterceptor mCommandProcessor; private final EventHandler<String> mCommandProcessor; private @Nullable String mCurrentSearch; private boolean mSearchExpanded; Loading @@ -61,7 +62,7 @@ public class SearchViewManager implements public SearchViewManager( SearchManagerListener listener, CommandInterceptor commandProcessor, EventHandler<String> commandProcessor, @Nullable Bundle savedState) { assert (listener != null); Loading Loading
src/com/android/documentsui/BaseActivity.java +12 −3 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.Injector.Injected; import com.android.documentsui.NavigationViewManager.Breadcrumb; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; Loading Loading @@ -178,9 +179,17 @@ public abstract class BaseActivity // We piggy back on search input as it is the only text input // area in the app. But the functionality is independent // of "regular" search query processing. CommandInterceptor dbgCommands = new CommandInterceptor(mInjector.features); dbgCommands.add(new CommandInterceptor.DumpRootsCacheHandler(this)); mSearchManager = new SearchViewManager(searchListener, dbgCommands, icicle); final CommandInterceptor cmdInterceptor = new CommandInterceptor(mInjector.features); cmdInterceptor.add(new CommandInterceptor.DumpRootsCacheHandler(this)); // A tiny decorator that adds support for enabling CommandInterceptor // based on query input. It's sorta like CommandInterceptor, but its metaaahhh. EventHandler<String> queryInterceptor = CommandInterceptor.createDebugModeFlipper( mInjector.features, mInjector.debugHelper::toggleDebugMode, cmdInterceptor); mSearchManager = new SearchViewManager(searchListener, queryInterceptor, icicle); mSortController = SortController.create(this, mState.derivedMode, mState.sortModel); mPreferencesMonitor = new PreferencesMonitor( Loading
src/com/android/documentsui/base/DebugHelper.java +47 −37 Original line number Diff line number Diff line Loading @@ -26,29 +26,35 @@ import com.android.documentsui.R; * Debug menu tools requested by QA Fred. */ public class DebugHelper { private static final String TAG = "DebugHelper"; private static final int[][] code = new int[][] { private static final int[][] sCode = new int[][] { {19, 19, 20, 20, 21, 22, 21, 22, 30, 29}, {51, 51, 47, 47, 29, 32, 29, 32, 30, 29} }; private static final int[][] colors = new int[][] { private static final int[][] sColors = new int[][] { {0xFFDB3236, 0xFFB71C1C}, {0xFF3cba54, 0xFF1B5E20}, {0xFFf4c20d, 0xFFF9A825}, {0xFF4885ed, 0xFF0D47A1} }; private static final Pair[] messages = new Pair[]{ @SuppressWarnings("unchecked") private static final Pair<String, Integer>[] sMessages = new Pair[]{ new Pair<>("Woof Woof", R.drawable.debug_msg_1), new Pair<>("ワンワン", R.drawable.debug_msg_2) }; private boolean debugEnabled = false; private long lastTime = 0; private int position = 0; private int codeIndex = 0; private int colorIndex = 0; private int messageIndex = 0; private Injector<?> mInjector; private final Injector<?> mInjector; private boolean mDebugEnabled; private long mLastTime; private int mPosition; private int mCodeIndex; private int mColorIndex; private int mMessageIndex; public DebugHelper(Injector<?> injector) { mInjector = injector; Loading @@ -57,56 +63,60 @@ public class DebugHelper { public int[] getNextColors() { assert (mInjector.features.isDebugSupportEnabled()); if (colorIndex == colors.length) { colorIndex = 0; if (mColorIndex == sColors.length) { mColorIndex = 0; } return colors[colorIndex++]; return sColors[mColorIndex++]; } public Pair<String, Integer> getNextMessage() { assert (mInjector.features.isDebugSupportEnabled()); if (messageIndex == messages.length) { messageIndex = 0; if (mMessageIndex == sMessages.length) { mMessageIndex = 0; } return messages[messageIndex++]; return sMessages[mMessageIndex++]; } public void debugCheck(long time, int keyCode) { if (time == lastTime) { if (time == mLastTime) { return; } lastTime = time; mLastTime = time; if (position == 0) { for (int i = 0; i < code.length; i++) { if (keyCode == code[i][0]) { codeIndex = i; if (mPosition == 0) { for (int i = 0; i < sCode.length; i++) { if (keyCode == sCode[i][0]) { mCodeIndex = i; break; } } } if (keyCode == code[codeIndex][position]) { position++; } else if (position > 2 || (position == 2 && keyCode != code[codeIndex][0])) { position = 0; if (keyCode == sCode[mCodeIndex][mPosition]) { mPosition++; } else if (mPosition > 2 || (mPosition == 2 && keyCode != sCode[mCodeIndex][0])) { mPosition = 0; } if (position == code[codeIndex].length) { position = 0; debugEnabled = !debugEnabled; if (mPosition == sCode[mCodeIndex].length) { mPosition = 0; toggleDebugMode(); } } public void toggleDebugMode() { mDebugEnabled = !mDebugEnabled; // Actions is content-scope, so it can technically be null, though // not likely. if (mInjector.actions != null) { mInjector.actions.setDebugMode(debugEnabled); mInjector.actions.setDebugMode(mDebugEnabled); } if (Shared.VERBOSE) { Log.v(TAG, "Debug mode " + (debugEnabled ? "on" : "off")); } Log.v(TAG, "Debug mode " + (mDebugEnabled ? "on" : "off")); } } }
src/com/android/documentsui/base/Features.java +11 −4 Original line number Diff line number Diff line Loading @@ -90,8 +90,8 @@ public interface Features { @Override public boolean isCommandInterceptorEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES) && isEnabled(R.bool.feature_command_interceptor); assert(isDebugPolicyEnabled()); return isEnabled(R.bool.feature_command_interceptor); } @Override Loading @@ -104,10 +104,13 @@ public interface Features { return isEnabled(R.bool.feature_content_refresh); } private boolean isDebugPolicyEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES); } @Override public boolean isDebugSupportEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES) && !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN); return isDebugPolicyEnabled() && isFunPolicyEnabled(); } @Override Loading @@ -115,6 +118,10 @@ public interface Features { return isEnabled(R.bool.feature_folders_in_search_results); } private boolean isFunPolicyEnabled() { return !mUserMgr.hasUserRestriction(UserManager.DISALLOW_FUN); } @Override public boolean isGestureScaleEnabled() { return isEnabled(R.bool.feature_gesture_scale); Loading
src/com/android/documentsui/queries/CommandInterceptor.java +35 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public final class CommandInterceptor implements EventHandler<String> { @Override public boolean accept(String query) { if (!mFeatures.isDebugSupportEnabled()) { return false; } if (!mFeatures.isCommandInterceptorEnabled()) { if (DEBUG) Log.v(TAG, "Skipping input, command interceptor disabled."); return false; Loading Loading @@ -196,4 +200,35 @@ public final class CommandInterceptor implements EventHandler<String> { return false; } } /** * Wraps {@link CommandInterceptor} in a tiny decorator that adds support for * enabling CommandInterceptor feature based on some magic query input. * * <p>It's like super meta, maaaannn. */ public static final EventHandler<String> createDebugModeFlipper( Features features, Runnable debugFlipper, CommandInterceptor interceptor) { if (!features.isDebugSupportEnabled()) { return interceptor; } String magicString1 = COMMAND_PREFIX + "wwssadadba"; String magicString2 = "up up down down left right left right b a"; return new EventHandler<String>() { @Override public boolean accept(String query) { assert(features.isDebugSupportEnabled()); if (magicString1.equals(query) || magicString2.equals(query)) { debugFlipper.run(); } return interceptor.accept(query); } }; } }
src/com/android/documentsui/queries/SearchViewManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.widget.SearchView.OnQueryTextListener; import com.android.documentsui.R; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; Loading @@ -48,7 +49,7 @@ public class SearchViewManager implements private static final String TAG = "SearchManager"; private final SearchManagerListener mListener; private final CommandInterceptor mCommandProcessor; private final EventHandler<String> mCommandProcessor; private @Nullable String mCurrentSearch; private boolean mSearchExpanded; Loading @@ -61,7 +62,7 @@ public class SearchViewManager implements public SearchViewManager( SearchManagerListener listener, CommandInterceptor commandProcessor, EventHandler<String> commandProcessor, @Nullable Bundle savedState) { assert (listener != null); Loading