summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/commandline
diff options
context:
space:
mode:
authortwyen <twyen@google.com>2018-01-16 16:16:47 -0800
committerCopybara-Service <copybara-piper@google.com>2018-01-16 16:18:22 -0800
commit15cf6dc111d59ebefee15a586ff511ccdc29b545 (patch)
tree017f1c63d9be2ba32219533274c134807312986e /java/com/android/dialer/commandline
parent3eca69f8ceb91537f72ca6df797bf4cfd93bc41b (diff)
Implement dialer command line interface
This CL adds a generic interface to perform action and retrieve data in dialer. Test: Unit tests PiperOrigin-RevId: 182128015 Change-Id: Ib45ce9808bd4e0e4a9c9e05c0017e19c3213bb0d
Diffstat (limited to 'java/com/android/dialer/commandline')
-rw-r--r--java/com/android/dialer/commandline/Command.java31
-rw-r--r--java/com/android/dialer/commandline/CommandLineComponent.java40
-rw-r--r--java/com/android/dialer/commandline/CommandLineModule.java59
-rw-r--r--java/com/android/dialer/commandline/CommandLineReceiver.java91
-rw-r--r--java/com/android/dialer/commandline/CommandSupplier.java51
-rw-r--r--java/com/android/dialer/commandline/impl/Echo.java45
-rw-r--r--java/com/android/dialer/commandline/impl/Help.java89
-rw-r--r--java/com/android/dialer/commandline/impl/Version.java58
8 files changed, 464 insertions, 0 deletions
diff --git a/java/com/android/dialer/commandline/Command.java b/java/com/android/dialer/commandline/Command.java
new file mode 100644
index 000000000..5a35d4002
--- /dev/null
+++ b/java/com/android/dialer/commandline/Command.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline;
+
+import android.support.annotation.NonNull;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/** Handles a Command from {@link CommandLineReceiver}. */
+public interface Command {
+
+ ListenableFuture<String> run(ImmutableList<String> args);
+
+ /** Describe the command when "help" is listing available commands. */
+ @NonNull
+ String getShortDescription();
+}
diff --git a/java/com/android/dialer/commandline/CommandLineComponent.java b/java/com/android/dialer/commandline/CommandLineComponent.java
new file mode 100644
index 000000000..c9abc532d
--- /dev/null
+++ b/java/com/android/dialer/commandline/CommandLineComponent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline;
+
+import android.content.Context;
+import com.android.dialer.function.Supplier;
+import com.android.dialer.inject.HasRootComponent;
+import com.google.common.collect.ImmutableMap;
+import dagger.Subcomponent;
+
+/** Component to get all available commands. */
+@Subcomponent
+public abstract class CommandLineComponent {
+
+ public abstract Supplier<ImmutableMap<String, Command>> commandSupplier();
+
+ public static CommandLineComponent get(Context context) {
+ return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component())
+ .commandLineComponent();
+ }
+
+ /** Used to refer to the root application component. */
+ public interface HasComponent {
+ CommandLineComponent commandLineComponent();
+ }
+}
diff --git a/java/com/android/dialer/commandline/CommandLineModule.java b/java/com/android/dialer/commandline/CommandLineModule.java
new file mode 100644
index 000000000..366899e5e
--- /dev/null
+++ b/java/com/android/dialer/commandline/CommandLineModule.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline;
+
+import com.android.dialer.commandline.impl.Echo;
+import com.android.dialer.commandline.impl.Help;
+import com.android.dialer.commandline.impl.Version;
+import com.android.dialer.function.Supplier;
+import com.google.common.collect.ImmutableMap;
+import dagger.Module;
+import dagger.Provides;
+import javax.inject.Inject;
+
+/** Provides {@link Command} */
+@Module
+public abstract class CommandLineModule {
+
+ @Provides
+ static Supplier<ImmutableMap<String, Command>> provideCommandSupplier(
+ AospCommandInjector aospCommandInjector) {
+
+ return aospCommandInjector.inject(CommandSupplier.builder()).build();
+ }
+
+ /** Injects standard commands to the builder */
+ public static class AospCommandInjector {
+ private final Help help;
+ private final Version version;
+ private final Echo echo;
+
+ @Inject
+ AospCommandInjector(Help help, Version version, Echo echo) {
+ this.help = help;
+ this.version = version;
+ this.echo = echo;
+ }
+
+ public CommandSupplier.Builder inject(CommandSupplier.Builder builder) {
+ builder.addCommand("help", help);
+ builder.addCommand("version", version);
+ builder.addCommand("echo", echo);
+ return builder;
+ }
+ }
+}
diff --git a/java/com/android/dialer/commandline/CommandLineReceiver.java b/java/com/android/dialer/commandline/CommandLineReceiver.java
new file mode 100644
index 000000000..baaadf054
--- /dev/null
+++ b/java/com/android/dialer/commandline/CommandLineReceiver.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import com.android.dialer.buildtype.BuildType;
+import com.android.dialer.common.LogUtil;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
+
+/**
+ * Receives broadcasts to the component from adb shell. Must be on bugfood or have debug logging
+ * enabled.
+ */
+public class CommandLineReceiver extends BroadcastReceiver {
+
+ public static final String COMMAND = "command";
+ public static final String ARGS = "args";
+ public static final String TAG = "tag";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String outputTag = intent.getStringExtra(TAG);
+ if (outputTag == null) {
+ LogUtil.e("CommandLineReceiver", "missing tag");
+ return;
+ }
+ if (!LogUtil.isDebugEnabled() && BuildType.get() != BuildType.BUGFOOD) {
+ LogUtil.i(outputTag, "DISABLED");
+ return;
+ }
+ Command command =
+ CommandLineComponent.get(context)
+ .commandSupplier()
+ .get()
+ .get(intent.getStringExtra(COMMAND));
+ if (command == null) {
+ LogUtil.i(outputTag, "unknown command " + intent.getStringExtra(COMMAND));
+ return;
+ }
+
+ ImmutableList<String> args =
+ intent.hasExtra(ARGS)
+ ? ImmutableList.copyOf(intent.getStringArrayExtra(ARGS))
+ : ImmutableList.of();
+
+ try {
+ Futures.addCallback(
+ command.run(args),
+ new FutureCallback<String>() {
+ @Override
+ public void onSuccess(String response) {
+ if (TextUtils.isEmpty(response)) {
+ LogUtil.i(outputTag, "EMPTY");
+ } else {
+ LogUtil.i(outputTag, response);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ // LogUtil.e(tag, message, e) prints 2 entries where only the first one can be
+ // intercepted by the script. Compose the string instead.
+ LogUtil.e(outputTag, "error running command future", throwable);
+ }
+ },
+ MoreExecutors.directExecutor());
+ } catch (Throwable throwable) {
+ LogUtil.e(outputTag, "error running command", throwable);
+ }
+ }
+}
diff --git a/java/com/android/dialer/commandline/CommandSupplier.java b/java/com/android/dialer/commandline/CommandSupplier.java
new file mode 100644
index 000000000..7789258c8
--- /dev/null
+++ b/java/com/android/dialer/commandline/CommandSupplier.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline;
+
+import com.android.dialer.function.Supplier;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+
+/** Supplies commands */
+@AutoValue
+public abstract class CommandSupplier implements Supplier<ImmutableMap<String, Command>> {
+
+ public static Builder builder() {
+ return new AutoValue_CommandSupplier.Builder();
+ }
+
+ public abstract ImmutableMap<String, Command> commands();
+
+ @Override
+ public ImmutableMap<String, Command> get() {
+ return commands();
+ }
+
+ /** builder for the supplier */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ abstract ImmutableMap.Builder<String, Command> commandsBuilder();
+
+ public Builder addCommand(String key, Command command) {
+ commandsBuilder().put(key, command);
+ return this;
+ }
+
+ public abstract CommandSupplier build();
+ }
+}
diff --git a/java/com/android/dialer/commandline/impl/Echo.java b/java/com/android/dialer/commandline/impl/Echo.java
new file mode 100644
index 000000000..b5f2f084b
--- /dev/null
+++ b/java/com/android/dialer/commandline/impl/Echo.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline.impl;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import com.android.dialer.commandline.Command;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.inject.Inject;
+
+/** Print arguments. */
+public class Echo implements Command {
+
+ @VisibleForTesting
+ @Inject
+ public Echo() {}
+
+ @Override
+ public ListenableFuture<String> run(ImmutableList<String> args) {
+ return Futures.immediateFuture(TextUtils.join(" ", args));
+ }
+
+ @NonNull
+ @Override
+ public String getShortDescription() {
+ return "@hide Print all arguments.";
+ }
+}
diff --git a/java/com/android/dialer/commandline/impl/Help.java b/java/com/android/dialer/commandline/impl/Help.java
new file mode 100644
index 000000000..d0e008014
--- /dev/null
+++ b/java/com/android/dialer/commandline/impl/Help.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline.impl;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import com.android.dialer.commandline.Command;
+import com.android.dialer.commandline.CommandLineComponent;
+import com.android.dialer.inject.ApplicationContext;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import javax.inject.Inject;
+
+/** List available commands */
+public class Help implements Command {
+
+ private final Context context;
+
+ @Inject
+ Help(@ApplicationContext Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public ListenableFuture<String> run(ImmutableList<String> args) {
+ boolean showHidden = args.contains("--showHidden");
+
+ StringBuilder stringBuilder = new StringBuilder();
+ ImmutableMap<String, Command> commands =
+ CommandLineComponent.get(context).commandSupplier().get();
+ stringBuilder
+ .append(runOrThrow(commands.get("version")))
+ .append("\n")
+ .append("\n")
+ .append("usage: <command> [args...]\n")
+ .append("\n")
+ .append("<command>\n");
+
+ for (Entry<String, Command> entry : commands.entrySet()) {
+ String description = entry.getValue().getShortDescription();
+ if (!showHidden && description.startsWith("@hide ")) {
+ continue;
+ }
+ stringBuilder
+ .append("\t")
+ .append(entry.getKey())
+ .append("\t")
+ .append(description)
+ .append("\n");
+ }
+
+ return Futures.immediateFuture(stringBuilder.toString());
+ }
+
+ private static String runOrThrow(Command command) {
+ try {
+ return command.run(ImmutableList.of()).get();
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @NonNull
+ @Override
+ public String getShortDescription() {
+ return "Print this message";
+ }
+}
diff --git a/java/com/android/dialer/commandline/impl/Version.java b/java/com/android/dialer/commandline/impl/Version.java
new file mode 100644
index 000000000..5dfad9ae1
--- /dev/null
+++ b/java/com/android/dialer/commandline/impl/Version.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.dialer.commandline.impl;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.support.annotation.NonNull;
+import com.android.dialer.commandline.Command;
+import com.android.dialer.inject.ApplicationContext;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Locale;
+import javax.inject.Inject;
+
+/** Print the version name and code. */
+public class Version implements Command {
+
+ private final Context appContext;
+
+ @Inject
+ Version(@ApplicationContext Context context) {
+ this.appContext = context;
+ }
+
+ @Override
+ public ListenableFuture<String> run(ImmutableList<String> args) {
+ try {
+ PackageInfo info =
+ appContext.getPackageManager().getPackageInfo(appContext.getPackageName(), 0);
+ return Futures.immediateFuture(
+ String.format(Locale.US, "%s(%d)", info.versionName, info.versionCode));
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @NonNull
+ @Override
+ public String getShortDescription() {
+ return "Print dialer version";
+ }
+}