aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSvetoslav <svetoslavganov@google.com>2013-03-07 18:19:37 -0800
committerSvetoslav Ganov <svetoslavganov@google.com>2013-06-21 17:28:03 -0700
commit0fb6959ad364ee84e83c435d671228fb365f2084 (patch)
treec42238cf41c351aa7550599e13f308e7b9f0fae3
parentc861cbe15d3f6cf28aede372e81cb19fd46e3114 (diff)
downloadexperimental-0fb6959ad364ee84e83c435d671228fb365f2084.tar.gz
Print - print services
Change-Id: Iaf7cd0b49797721420a28fbecfd3f6557c35e64d
-rw-r--r--PrintApp/.classpath8
-rw-r--r--PrintApp/.project33
-rw-r--r--PrintApp/Android.mk13
-rw-r--r--PrintApp/AndroidManifest.xml24
-rw-r--r--PrintApp/res/drawable-hdpi/ic_launcher.pngbin0 -> 3014 bytes
-rw-r--r--PrintApp/res/drawable-ldpi/ic_launcher.pngbin0 -> 1504 bytes
-rw-r--r--PrintApp/res/drawable-mdpi/ic_launcher.pngbin0 -> 1969 bytes
-rw-r--r--PrintApp/res/drawable-xhdpi/ic_launcher.pngbin0 -> 4006 bytes
-rw-r--r--PrintApp/res/layout/activity_main.xml124
-rw-r--r--PrintApp/res/menu/activity_main.xml10
-rw-r--r--PrintApp/res/values/strings.xml11
-rw-r--r--PrintApp/src/foo/bar/print/PrintActivity.java166
-rw-r--r--PrintApp/src/foo/bar/print/PrintedPdfDocument.java160
-rw-r--r--PrintService/.classpath8
-rw-r--r--PrintService/.project33
-rw-r--r--PrintService/Android.mk13
-rw-r--r--PrintService/AndroidManifest.xml37
-rw-r--r--PrintService/res/drawable-hdpi/ic_launcher.pngbin0 -> 3014 bytes
-rw-r--r--PrintService/res/drawable-ldpi/ic_launcher.pngbin0 -> 1504 bytes
-rw-r--r--PrintService/res/drawable-mdpi/ic_launcher.pngbin0 -> 1969 bytes
-rw-r--r--PrintService/res/drawable-xhdpi/ic_launcher.pngbin0 -> 4006 bytes
-rw-r--r--PrintService/res/layout/activity_main.xml13
-rw-r--r--PrintService/res/values/strings.xml18
-rw-r--r--PrintService/res/xml/printservice.xml3
-rw-r--r--PrintService/src/foo/bar/printservice/AddPrintersActivity.java13
-rw-r--r--PrintService/src/foo/bar/printservice/MyPrintService.java231
-rw-r--r--PrintService/src/foo/bar/printservice/SettingsActivity.java13
-rw-r--r--PrintService2/.classpath8
-rw-r--r--PrintService2/.project33
-rw-r--r--PrintService2/Android.mk13
-rw-r--r--PrintService2/AndroidManifest.xml35
-rw-r--r--PrintService2/res/drawable-hdpi/ic_launcher.pngbin0 -> 3014 bytes
-rw-r--r--PrintService2/res/drawable-ldpi/ic_launcher.pngbin0 -> 1504 bytes
-rw-r--r--PrintService2/res/drawable-mdpi/ic_launcher.pngbin0 -> 1969 bytes
-rw-r--r--PrintService2/res/drawable-xhdpi/ic_launcher.pngbin0 -> 4006 bytes
-rw-r--r--PrintService2/res/layout/activity_main.xml13
-rw-r--r--PrintService2/res/values/strings.xml16
-rw-r--r--PrintService2/res/xml/printservice.xml3
-rw-r--r--PrintService2/src/foo/bar/printservice2/MyPrintService.java231
-rw-r--r--PrintService2/src/foo/bar/printservice2/SettingsActivity.java15
-rw-r--r--TestBack/.classpath8
-rw-r--r--TestBack/.project33
-rw-r--r--TestBack/Android.mk13
-rw-r--r--TestBack/AndroidManifest.xml38
-rw-r--r--TestBack/res/drawable-hdpi/ic_action_search.pngbin0 -> 3120 bytes
-rw-r--r--TestBack/res/drawable-hdpi/ic_launcher.pngbin0 -> 3014 bytes
-rw-r--r--TestBack/res/drawable-ldpi/ic_launcher.pngbin0 -> 1504 bytes
-rw-r--r--TestBack/res/drawable-mdpi/ic_action_search.pngbin0 -> 3030 bytes
-rw-r--r--TestBack/res/drawable-mdpi/ic_launcher.pngbin0 -> 1969 bytes
-rw-r--r--TestBack/res/drawable-xhdpi/ic_action_search.pngbin0 -> 3199 bytes
-rw-r--r--TestBack/res/drawable-xhdpi/ic_launcher.pngbin0 -> 4006 bytes
-rw-r--r--TestBack/res/menu/activity_main.xml6
-rw-r--r--TestBack/res/values-v11/styles.xml5
-rw-r--r--TestBack/res/values-v14/styles.xml5
-rw-r--r--TestBack/res/values/strings.xml8
-rw-r--r--TestBack/res/values/styles.xml5
-rw-r--r--TestBack/res/xml/accessibilityservice.xml5
-rw-r--r--TestBack/src/foo/bar/testback/Foo.java45
-rw-r--r--TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java18
-rw-r--r--TestBack/src/foo/bar/testback/TestBackService.java145
60 files changed, 1632 insertions, 0 deletions
diff --git a/PrintApp/.classpath b/PrintApp/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/PrintApp/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/PrintApp/.project b/PrintApp/.project
new file mode 100644
index 0000000..507c2e2
--- /dev/null
+++ b/PrintApp/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>TestBack</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/PrintApp/Android.mk b/PrintApp/Android.mk
new file mode 100644
index 0000000..7cea0ab
--- /dev/null
+++ b/PrintApp/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Print
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/PrintApp/AndroidManifest.xml b/PrintApp/AndroidManifest.xml
new file mode 100644
index 0000000..7528f28
--- /dev/null
+++ b/PrintApp/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar.print"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="KeyLimePie"
+ android:targetSdkVersion="KeyLimePie" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="false" >
+ <activity
+ android:name=".PrintActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/PrintApp/res/drawable-hdpi/ic_launcher.png b/PrintApp/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a301d57
--- /dev/null
+++ b/PrintApp/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/PrintApp/res/drawable-ldpi/ic_launcher.png b/PrintApp/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..2c2a58b
--- /dev/null
+++ b/PrintApp/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/PrintApp/res/drawable-mdpi/ic_launcher.png b/PrintApp/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f91f736
--- /dev/null
+++ b/PrintApp/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/PrintApp/res/drawable-xhdpi/ic_launcher.png b/PrintApp/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..96095ec
--- /dev/null
+++ b/PrintApp/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/PrintApp/res/layout/activity_main.xml b/PrintApp/res/layout/activity_main.xml
new file mode 100644
index 0000000..8a3c72a
--- /dev/null
+++ b/PrintApp/res/layout/activity_main.xml
@@ -0,0 +1,124 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/name">
+ </TextView>
+
+ <EditText
+ android:layout_width="1150dip"
+ android:layout_height="wrap_content"
+ android:hint="@string/enter_name">
+ </EditText>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/name">
+ </TextView>
+
+ <EditText
+ android:layout_width="1150dip"
+ android:layout_height="wrap_content"
+ android:hint="@string/enter_name">
+ </EditText>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/name">
+ </TextView>
+
+ <EditText
+ android:layout_width="1150dip"
+ android:layout_height="wrap_content"
+ android:hint="@string/enter_name">
+ </EditText>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/name">
+ </TextView>
+
+ <EditText
+ android:layout_width="1150dip"
+ android:layout_height="wrap_content"
+ android:hint="@string/enter_name">
+ </EditText>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/name">
+ </TextView>
+
+ <EditText
+ android:layout_width="1150dip"
+ android:layout_height="wrap_content"
+ android:hint="@string/enter_name">
+ </EditText>
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"/>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/PrintApp/res/menu/activity_main.xml b/PrintApp/res/menu/activity_main.xml
new file mode 100644
index 0000000..31bb883
--- /dev/null
+++ b/PrintApp/res/menu/activity_main.xml
@@ -0,0 +1,10 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_settings"
+ android:title="@string/menu_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+ <item android:id="@+id/menu_print"
+ android:title="@string/print"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+</menu>
diff --git a/PrintApp/res/values/strings.xml b/PrintApp/res/values/strings.xml
new file mode 100644
index 0000000..352494a
--- /dev/null
+++ b/PrintApp/res/values/strings.xml
@@ -0,0 +1,11 @@
+<resources>
+
+ <string name="app_name">Print</string>
+ <string name="menu_settings">Settings</string>
+ <string name="title_activity_main">MainActivity</string>
+ <string name="print">Print</string>
+ <string name="name">Name</string>
+ <string name="enter_name">Enter your name</string>
+ <string name="done">Done</string>
+
+</resources> \ No newline at end of file
diff --git a/PrintApp/src/foo/bar/print/PrintActivity.java b/PrintApp/src/foo/bar/print/PrintActivity.java
new file mode 100644
index 0000000..02046d4
--- /dev/null
+++ b/PrintApp/src/foo/bar/print/PrintActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2013 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 foo.bar.print;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.CancellationSignal.OnCancelListener;
+import android.print.PageRange;
+import android.print.PrintAdapter;
+import android.print.PrintAdapterInfo;
+import android.print.PrintAttributes;
+import android.print.PrintJob;
+import android.print.PrintManager;
+import android.print.pdf.PdfDocument.Page;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.util.List;
+
+/**
+ * Simple sample of how to use the print APIs.
+ */
+public class PrintActivity extends Activity {
+
+ public static final String LOG_TAG = "PrintActivity";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.activity_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (!super.onOptionsItemSelected(item)) {
+ if (item.getItemId() == R.id.menu_print) {
+ printView();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void printFileSimple() {
+ PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
+
+ PrintJob printJob = printManager.print("My Print Job", new File("foo.pdf"), null);
+
+ if (printJob != null) {
+ /* Yay, we scheduled something to be printed!!! */
+ }
+ }
+
+ private void printView() {
+ PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
+
+ final View view = findViewById(R.id.content);
+
+ PrintJob printJob = printManager.print("Print_View",
+ new PrintAdapter() {
+ private PrintedPdfDocument mPdfDocument;
+
+ @Override
+ public void onStarted() {
+ Log.i(LOG_TAG, "onStarted");
+ super.onStarted();
+ }
+
+ @Override
+ public boolean onPrintAttributesChanged(PrintAttributes attributes) {
+ Log.i(LOG_TAG, "onPrintAttributesChanged");
+ mPdfDocument = new PrintedPdfDocument(PrintActivity.this, attributes);
+ Page page = mPdfDocument.startPage();
+ view.draw(page.getCanvas());
+ mPdfDocument.finishPage(page);
+ return true;
+ }
+
+ @Override
+ public void onPrint(final List<PageRange> pages,
+ final FileDescriptor destination,
+ final CancellationSignal canclleationSignal,
+ final PrintProgressListener progressListener) {
+ Log.i(LOG_TAG, "onPrint");
+ final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ mPdfDocument.writeTo(new FileOutputStream(destination));
+ } finally {
+ mPdfDocument.close();
+ IoUtils.closeQuietly(destination);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ progressListener.onWriteFinished(pages);
+ }
+
+ @Override
+ protected void onCancelled(Void result) {
+ progressListener.onWriteFailed("Cancelled");
+ }
+ };
+
+ canclleationSignal.setOnCancelListener(new OnCancelListener() {
+ @Override
+ public void onCancel() {
+ task.cancel(true);
+ }
+ });
+
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
+ @Override
+ public void onFinished() {
+ Log.i(LOG_TAG, "onFinished");
+ super.onFinished();
+ }
+
+ @Override
+ public PrintAdapterInfo getInfo() {
+ Log.i(LOG_TAG, "getInfo");
+ return new PrintAdapterInfo.Builder().setPageCount(1).create();
+ }
+ }, new PrintAttributes.Builder().create());
+
+ if (printJob != null) {
+ /* Yay, we scheduled something to be printed!!! */
+ }
+ }
+}
diff --git a/PrintApp/src/foo/bar/print/PrintedPdfDocument.java b/PrintApp/src/foo/bar/print/PrintedPdfDocument.java
new file mode 100644
index 0000000..f6cdb4a
--- /dev/null
+++ b/PrintApp/src/foo/bar/print/PrintedPdfDocument.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2013 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 foo.bar.print;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.pdf.PdfDocument;
+import android.print.pdf.PdfDocument.Page;
+import android.print.pdf.PdfDocument.PageInfo;
+import android.util.DisplayMetrics;
+import android.view.Display;
+
+import java.io.OutputStream;
+
+/**
+ * This class is a helper for printing content to a different media
+ * size. The printed content will be as large as it would be on the
+ * screen.
+ *
+ * THIS IS A TEST CODE AND IS HIDDEN
+ *
+ * @hide
+ */
+public final class PrintedPdfDocument {
+ private static final int MILS_PER_INCH = 1000;
+
+ /**
+ * Maximum bitmap size as defined in Skia's native code (see SkCanvas.cpp,
+ * SkDraw.cpp)
+ */
+ private static final int MAXMIMUM_BITMAP_SIZE = 32766;
+
+ private final PdfDocument mDocument = PdfDocument.open();
+ private final Rect mPageSize = new Rect();
+ private final Rect mContentSize = new Rect();
+
+ private final int mCanvasDensityDpi;
+ private final Matrix mContentToPageTransform;
+
+ private Matrix mTempMatrix;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param context Context instance for accessing resources and services.
+ * @param attributes The {@link PrintAttributes} to user.
+ */
+ public PrintedPdfDocument(Context context, PrintAttributes attributes) {
+ MediaSize mediaSize = attributes.getMediaSize();
+ Resolution resolution = attributes.getResolution();
+
+ // TODO: What to do if horizontal and vertical DPI differ?
+ mCanvasDensityDpi = Math.max(attributes.getResolution().getHorizontalDpi(), attributes
+ .getResolution().getVerticalDpi());
+
+ // Figure out the scale since the content and the target DPI may differ.
+ DisplayMetrics metrics = new DisplayMetrics();
+ DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ dm.getDisplay(Display.DEFAULT_DISPLAY).getMetrics(metrics);
+ final float scaleFactor = ((float) mCanvasDensityDpi) / metrics.densityDpi;
+ mContentToPageTransform = new Matrix();
+ mContentToPageTransform.setScale(scaleFactor, scaleFactor);
+
+ // Compute the size of the target canvas from the attributes.
+ final int pageWidth = (mediaSize.getWidthMils() / MILS_PER_INCH)
+ * resolution.getHorizontalDpi();
+ final int pageHeight = (mediaSize.getHeightMils() / MILS_PER_INCH)
+ * resolution.getVerticalDpi();
+ mPageSize.set(0, 0, pageWidth, pageHeight);
+
+ // Compute the content size from the attributes.
+ Margins margins = attributes.getMargins();
+ final int marginLeft = (margins.getLeftMils() / MILS_PER_INCH)
+ * resolution.getHorizontalDpi();
+ final int marginTop = (margins.getTopMils() / MILS_PER_INCH) * resolution.getVerticalDpi();
+ final int marginRight = (margins.getRightMils() / MILS_PER_INCH)
+ * resolution.getHorizontalDpi();
+ final int marginBottom = (margins.getBottomMils() / MILS_PER_INCH)
+ * resolution.getVerticalDpi();
+ mContentSize.set(mPageSize.left + marginLeft, mPageSize.top + marginTop, mPageSize.right
+ - marginRight, mPageSize.bottom - marginBottom);
+ }
+
+ /**
+ * Starts a new page.
+ *
+ * @return The started page.
+ */
+ public Page startPage() {
+ return startPage(null);
+ }
+
+ /**
+ * Starts a new page.
+ *
+ * @param additionalTransform Additional initial transform.
+ * @return The started page.
+ */
+ public Page startPage(Matrix additionalTransform) {
+ Matrix transform = null;
+ if (additionalTransform != null) {
+ if (mTempMatrix == null) {
+ transform = mTempMatrix = new Matrix();
+ }
+ transform.set(mContentToPageTransform);
+ transform.postConcat(additionalTransform);
+ } else {
+ transform = mContentToPageTransform;
+ }
+ PageInfo pageInfo = new PageInfo.Builder(mPageSize, 0, mCanvasDensityDpi).create();
+ Page page = mDocument.startPage(pageInfo);
+ return page;
+ }
+
+ /**
+ * Finishes a page.
+ *
+ * @param page The page to finish.
+ */
+ public void finishPage(Page page) {
+ mDocument.finishPage(page);
+ }
+
+ /**
+ * Writes the document to a stream.
+ *
+ * @param out The destination stream.
+ */
+ public void writeTo(OutputStream out) {
+ mDocument.writeTo(out);
+ }
+
+ /**
+ * Closes the document.
+ */
+ public void close() {
+ mDocument.close();
+ }
+}
diff --git a/PrintService/.classpath b/PrintService/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/PrintService/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/PrintService/.project b/PrintService/.project
new file mode 100644
index 0000000..507c2e2
--- /dev/null
+++ b/PrintService/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>TestBack</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/PrintService/Android.mk b/PrintService/Android.mk
new file mode 100644
index 0000000..7c5d5fa
--- /dev/null
+++ b/PrintService/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PrintService
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/PrintService/AndroidManifest.xml b/PrintService/AndroidManifest.xml
new file mode 100644
index 0000000..096e7cd
--- /dev/null
+++ b/PrintService/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar.printservice"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="KeyLimePie"
+ android:targetSdkVersion="KeyLimePie" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="false" >
+ <service
+ android:name=".MyPrintService"
+ android:permission="android.permission.BIND_PRINT_SERVICE">
+ <intent-filter>
+ <action android:name="android.printservice.PrintService" />
+ </intent-filter>
+ <meta-data
+ android:name="android.printservice"
+ android:resource="@xml/printservice">
+ </meta-data>
+ </service>
+ <activity
+ android:name=".SettingsActivity"
+ android:label="@string/settings_activity_label"
+ android:permission="android.permission.BIND_PRINT_SERVICE">
+ </activity>
+ <activity
+ android:name=".AddPrintersActivity"
+ android:label="@string/add_pritners_activity_label"
+ android:permission="android.permission.BIND_PRINT_SERVICE">
+ </activity>
+ </application>
+
+</manifest>
diff --git a/PrintService/res/drawable-hdpi/ic_launcher.png b/PrintService/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a301d57
--- /dev/null
+++ b/PrintService/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService/res/drawable-ldpi/ic_launcher.png b/PrintService/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..2c2a58b
--- /dev/null
+++ b/PrintService/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/PrintService/res/drawable-mdpi/ic_launcher.png b/PrintService/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f91f736
--- /dev/null
+++ b/PrintService/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService/res/drawable-xhdpi/ic_launcher.png b/PrintService/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..96095ec
--- /dev/null
+++ b/PrintService/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService/res/layout/activity_main.xml b/PrintService/res/layout/activity_main.xml
new file mode 100644
index 0000000..78184ea
--- /dev/null
+++ b/PrintService/res/layout/activity_main.xml
@@ -0,0 +1,13 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity" >
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/settings">
+ </TextView>
+
+</LinearLayout>
diff --git a/PrintService/res/values/strings.xml b/PrintService/res/values/strings.xml
new file mode 100644
index 0000000..7a4b0b1
--- /dev/null
+++ b/PrintService/res/values/strings.xml
@@ -0,0 +1,18 @@
+<resources>
+
+ <string name="app_name">Print Service</string>
+ <string name="description">This print serivice exposes one fake printer and
+ on print sends an email to svetoslavganov@google.com</string>
+ <string name="settings">This is an activitiy with some print service settings.</string>
+ <string name="settings_activity_label">Settings activity</string>
+ <string name="add_pritners_activity_label">Add printers activity</string>
+
+ <string name="resolution_200x200">200x200</string>
+ <string name="resolution_300x300">300x300</string>
+ <string name="resolution_600x600">600x600</string>
+ <string name="input_tray_first">First input tray</string>
+ <string name="input_tray_second">Second input tray</string>
+ <string name="output_tray_first">First output tray</string>
+ <string name="output_tray_second">Second output tray</string>
+
+</resources>
diff --git a/PrintService/res/xml/printservice.xml b/PrintService/res/xml/printservice.xml
new file mode 100644
index 0000000..667bef7
--- /dev/null
+++ b/PrintService/res/xml/printservice.xml
@@ -0,0 +1,3 @@
+<print-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity="foo.bar.printservice.SettingsActivity"
+ android:addPrintersActivity="foo.bar.printservice.AddPrintersActivity"/>
diff --git a/PrintService/src/foo/bar/printservice/AddPrintersActivity.java b/PrintService/src/foo/bar/printservice/AddPrintersActivity.java
new file mode 100644
index 0000000..1a0bc18
--- /dev/null
+++ b/PrintService/src/foo/bar/printservice/AddPrintersActivity.java
@@ -0,0 +1,13 @@
+package foo.bar.printservice;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class AddPrintersActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/PrintService/src/foo/bar/printservice/MyPrintService.java b/PrintService/src/foo/bar/printservice/MyPrintService.java
new file mode 100644
index 0000000..010c987
--- /dev/null
+++ b/PrintService/src/foo/bar/printservice/MyPrintService.java
@@ -0,0 +1,231 @@
+package foo.bar.printservice;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintAttributes.Tray;
+import android.print.PrintJobInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MyPrintService extends PrintService {
+
+ private static final String LOG_TAG = MyPrintService.class.getSimpleName();
+
+ private Handler mHandler;
+
+ @Override
+ protected void onConnected() {
+ mHandler = new MyHandler(getMainLooper());
+ Log.i(LOG_TAG, "#onConnected()");
+ }
+
+ @Override
+ protected void onDisconnected() {
+ Log.i(LOG_TAG, "#onDisconnected()");
+ }
+
+ @Override
+ protected void onStartPrinterDiscovery() {
+ Log.i(LOG_TAG, "#onStartDiscoverPrinters()");
+ Message message1 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_FIRST_FAKE_PRINTER);
+ mHandler.sendMessageDelayed(message1, 0);
+
+ Message message2 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_SECOND_FAKE_PRINTER);
+ mHandler.sendMessageDelayed(message2, 10000);
+ }
+
+ @Override
+ protected void onStopPrinterDiscovery() {
+ Log.i(LOG_TAG, "#onStopDiscoverPrinters()");
+ }
+
+ @Override
+ public void onPrintJobQueued(final PrintJob printJob) {
+ Log.i(LOG_TAG, "#onPrintJobPending()");
+ PrintJobInfo info = printJob.getInfo();
+ final File file = new File(getFilesDir(), info.getLabel() + ".pdf");
+ if (file.exists()) {
+ file.delete();
+ }
+ AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ InputStream in = new BufferedInputStream(
+ new FileInputStream(printJob.getData()));
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ final byte[] buffer = new byte[8192];
+ while (true) {
+ final int readByteCount = in.read(buffer);
+ if (readByteCount < 0) {
+ break;
+ }
+ out.write(buffer, 0, readByteCount);
+ }
+ } catch (IOException ioe) {
+ /* ignore */
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ file.setExecutable(true, false);
+ file.setWritable(true, false);
+ file.setReadable(true, false);
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.fromFile(file), "application/pdf");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent, null);
+
+ if (printJob.isQueued()) {
+ printJob.start();
+ }
+
+ PrintJobInfo info = printJob.getInfo();
+ Toast.makeText(MyPrintService.this,
+ "Printer: " + info.getPrinterId().getLocalId()
+ + " copies: " + info.getAttributes().getCopies(),
+ Toast.LENGTH_SHORT).show();
+
+ if (printJob.isStarted()) {
+ printJob.complete();
+ }
+ }
+ };
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ private void addFirstFakePrinter() {
+ PrinterId printerId = generatePrinterId("1");
+ PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 1")
+ .setStatus(PrinterInfo.STATUS_READY)
+ .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A2, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A3, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A4, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A6, false)
+ .addMediaSize(PrintAttributes.MediaSize.NA_LETTER, true)
+ .addResolution(new Resolution("R1", getPackageName(),
+ R.string.resolution_600x600, 600, 600), true)
+ .addInputTray(new Tray("FirstInputTray", getPackageName(),
+ R.string.input_tray_first), false)
+ .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
+ R.string.output_tray_first), false)
+ .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
+ | PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
+ PrintAttributes.DUPLEX_MODE_NONE)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .setFittingModes(PrintAttributes.FITTING_MODE_NONE
+ | PrintAttributes.FITTING_MODE_FIT_TO_PAGE,
+ PrintAttributes.FITTING_MODE_NONE)
+ .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+ | PrintAttributes.ORIENTATION_LANDSCAPE,
+ PrintAttributes.ORIENTATION_PORTRAIT)
+ .create();
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ printers.add(printer);
+ addDiscoveredPrinters(printers);
+ }
+
+ private void addSecondFakePrinter() {
+ PrinterId printerId = generatePrinterId("2");
+ PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 2")
+ .setStatus(PrinterInfo.STATUS_READY)
+ .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
+ .addResolution(new Resolution("R1", getPackageName(),
+ R.string.resolution_200x200, 200, 200), true)
+ .addResolution(new Resolution("R2", getPackageName(),
+ R.string.resolution_300x300, 300, 300), false)
+ .addInputTray(new Tray("FirstInputTray", getPackageName(),
+ R.string.input_tray_first), false)
+ .addInputTray(new Tray("SecondInputTray", getPackageName(),
+ R.string.input_tray_second), true)
+ .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
+ R.string.output_tray_first), false)
+ .addOutputTray(new Tray("SecondOutputTray", getPackageName(),
+ R.string.output_tray_second), true)
+ .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
+ | PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
+ PrintAttributes.DUPLEX_MODE_SHORT_EDGE)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_MONOCHROME)
+ .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE
+ | PrintAttributes.FITTING_MODE_NONE,
+ PrintAttributes.FITTING_MODE_FIT_TO_PAGE)
+ .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+ | PrintAttributes.ORIENTATION_LANDSCAPE,
+ PrintAttributes.ORIENTATION_LANDSCAPE)
+ .create();
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ printers.add(printer);
+ addDiscoveredPrinters(printers);
+ }
+
+ private final class MyHandler extends Handler {
+
+ public static final int MESSAGE_ADD_FIRST_FAKE_PRINTER = 1;
+ public static final int MESSAGE_ADD_SECOND_FAKE_PRINTER = 2;
+
+ public MyHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_ADD_FIRST_FAKE_PRINTER: {
+ addFirstFakePrinter();
+ } break;
+ case MESSAGE_ADD_SECOND_FAKE_PRINTER: {
+ addSecondFakePrinter();
+ } break;
+ }
+ }
+ }
+}
diff --git a/PrintService/src/foo/bar/printservice/SettingsActivity.java b/PrintService/src/foo/bar/printservice/SettingsActivity.java
new file mode 100644
index 0000000..21ab419
--- /dev/null
+++ b/PrintService/src/foo/bar/printservice/SettingsActivity.java
@@ -0,0 +1,13 @@
+package foo.bar.printservice;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SettingsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/PrintService2/.classpath b/PrintService2/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/PrintService2/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/PrintService2/.project b/PrintService2/.project
new file mode 100644
index 0000000..507c2e2
--- /dev/null
+++ b/PrintService2/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>TestBack</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/PrintService2/Android.mk b/PrintService2/Android.mk
new file mode 100644
index 0000000..3dda6c8
--- /dev/null
+++ b/PrintService2/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PrintService2
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/PrintService2/AndroidManifest.xml b/PrintService2/AndroidManifest.xml
new file mode 100644
index 0000000..e92d635
--- /dev/null
+++ b/PrintService2/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar.printservice2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="KeyLimePie"
+ android:targetSdkVersion="KeyLimePie" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="false" >
+ <service
+ android:name=".MyPrintService"
+ android:permission="android.permission.BIND_PRINT_SERVICE">
+ <intent-filter>
+ <action android:name="android.printservice.PrintService" />
+ </intent-filter>
+ <meta-data
+ android:name="android.printservice"
+ android:resource="@xml/printservice">
+ </meta-data>
+ </service>
+ <activity
+ android:name=".SettingsActivity"
+ android:label="@string/app_name"
+ android:permission="android.permission.BIND_PRINT_SERVICE">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/PrintService2/res/drawable-hdpi/ic_launcher.png b/PrintService2/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a301d57
--- /dev/null
+++ b/PrintService2/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService2/res/drawable-ldpi/ic_launcher.png b/PrintService2/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..2c2a58b
--- /dev/null
+++ b/PrintService2/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/PrintService2/res/drawable-mdpi/ic_launcher.png b/PrintService2/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f91f736
--- /dev/null
+++ b/PrintService2/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService2/res/drawable-xhdpi/ic_launcher.png b/PrintService2/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..96095ec
--- /dev/null
+++ b/PrintService2/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/PrintService2/res/layout/activity_main.xml b/PrintService2/res/layout/activity_main.xml
new file mode 100644
index 0000000..78184ea
--- /dev/null
+++ b/PrintService2/res/layout/activity_main.xml
@@ -0,0 +1,13 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity" >
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:text="@string/settings">
+ </TextView>
+
+</LinearLayout>
diff --git a/PrintService2/res/values/strings.xml b/PrintService2/res/values/strings.xml
new file mode 100644
index 0000000..6fb171b
--- /dev/null
+++ b/PrintService2/res/values/strings.xml
@@ -0,0 +1,16 @@
+<resources>
+
+ <string name="app_name">Print Service 2</string>
+ <string name="description">This print serivice exposes one fake printer and
+ on print sends an email to svetoslavganov@google.com</string>
+ <string name="settings">This is an activitiy with some print service settings.</string>
+
+ <string name="resolution_200x200">200x200</string>
+ <string name="resolution_300x300">300x300</string>
+ <string name="resolution_600x600">600x600</string>
+ <string name="input_tray_first">First input tray</string>
+ <string name="input_tray_second">Second input tray</string>
+ <string name="output_tray_first">First output tray</string>
+ <string name="output_tray_second">Second output tray</string>
+
+</resources>
diff --git a/PrintService2/res/xml/printservice.xml b/PrintService2/res/xml/printservice.xml
new file mode 100644
index 0000000..44fa285
--- /dev/null
+++ b/PrintService2/res/xml/printservice.xml
@@ -0,0 +1,3 @@
+<print-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity="foo.bar.printservice2.SettingsActivity"
+ android:description="@string/description"/>
diff --git a/PrintService2/src/foo/bar/printservice2/MyPrintService.java b/PrintService2/src/foo/bar/printservice2/MyPrintService.java
new file mode 100644
index 0000000..8a4227a
--- /dev/null
+++ b/PrintService2/src/foo/bar/printservice2/MyPrintService.java
@@ -0,0 +1,231 @@
+package foo.bar.printservice2;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintAttributes.Tray;
+import android.print.PrintJobInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MyPrintService extends PrintService {
+
+ private static final String LOG_TAG = MyPrintService.class.getSimpleName();
+
+ private Handler mHandler;
+
+ @Override
+ protected void onConnected() {
+ mHandler = new MyHandler(getMainLooper());
+ Log.i(LOG_TAG, "#onConnected()");
+ }
+
+ @Override
+ protected void onDisconnected() {
+ Log.i(LOG_TAG, "#onDisconnected()");
+ }
+
+ @Override
+ protected void onStartPrinterDiscovery() {
+ Log.i(LOG_TAG, "#onStartDiscoverPrinters()");
+ Message message1 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_FIRST_FAKE_PRINTER);
+ mHandler.sendMessageDelayed(message1, 0);
+
+ Message message2 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_SECOND_FAKE_PRINTER);
+ mHandler.sendMessageDelayed(message2, 10000);
+ }
+
+ @Override
+ protected void onStopPrinterDiscovery() {
+ Log.i(LOG_TAG, "#onStopDiscoverPrinters()");
+ }
+
+ @Override
+ public void onPrintJobQueued(final PrintJob printJob) {
+ Log.i(LOG_TAG, "#onPrintJobPending()");
+ PrintJobInfo info = printJob.getInfo();
+ final File file = new File(getFilesDir(), info.getLabel() + ".pdf");
+ if (file.exists()) {
+ file.delete();
+ }
+ AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ InputStream in = new BufferedInputStream(
+ new FileInputStream(printJob.getData()));
+ OutputStream out = null;
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ final byte[] buffer = new byte[8192];
+ while (true) {
+ final int readByteCount = in.read(buffer);
+ if (readByteCount < 0) {
+ break;
+ }
+ out.write(buffer, 0, readByteCount);
+ }
+ } catch (IOException ioe) {
+ /* ignore */
+ } finally {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioe) {
+ /* ignore */
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ file.setExecutable(true, false);
+ file.setWritable(true, false);
+ file.setReadable(true, false);
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.fromFile(file), "application/pdf");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent, null);
+
+ if (printJob.isQueued()) {
+ printJob.start();
+ }
+
+ PrintJobInfo info = printJob.getInfo();
+ Toast.makeText(MyPrintService.this,
+ "Printer: " + info.getPrinterId().getLocalId()
+ + " copies: " + info.getAttributes().getCopies(),
+ Toast.LENGTH_SHORT).show();
+
+ if (printJob.isStarted()) {
+ printJob.complete();
+ }
+ }
+ };
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ private void addFirstFakePrinter() {
+ PrinterId printerId = generatePrinterId("1");
+ PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 1")
+ .setStatus(PrinterInfo.STATUS_READY)
+ .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A2, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A3, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A4, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A6, false)
+ .addMediaSize(PrintAttributes.MediaSize.NA_LETTER, true)
+ .addResolution(new Resolution("R1", getPackageName(),
+ R.string.resolution_600x600, 600, 600), true)
+ .addInputTray(new Tray("FirstInputTray", getPackageName(),
+ R.string.input_tray_first), false)
+ .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
+ R.string.output_tray_first), false)
+ .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
+ | PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
+ PrintAttributes.DUPLEX_MODE_NONE)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .setFittingModes(PrintAttributes.FITTING_MODE_NONE
+ | PrintAttributes.FITTING_MODE_FIT_TO_PAGE,
+ PrintAttributes.FITTING_MODE_NONE)
+ .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+ | PrintAttributes.ORIENTATION_LANDSCAPE,
+ PrintAttributes.ORIENTATION_PORTRAIT)
+ .create();
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ printers.add(printer);
+ addDiscoveredPrinters(printers);
+ }
+
+ private void addSecondFakePrinter() {
+ PrinterId printerId = generatePrinterId("2");
+ PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 2")
+ .setStatus(PrinterInfo.STATUS_READY)
+ .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true)
+ .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
+ .addResolution(new Resolution("R1", getPackageName(),
+ R.string.resolution_200x200, 200, 200), true)
+ .addResolution(new Resolution("R2", getPackageName(),
+ R.string.resolution_300x300, 300, 300), false)
+ .addInputTray(new Tray("FirstInputTray", getPackageName(),
+ R.string.input_tray_first), false)
+ .addInputTray(new Tray("SecondInputTray", getPackageName(),
+ R.string.input_tray_second), true)
+ .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
+ R.string.output_tray_first), false)
+ .addOutputTray(new Tray("SecondOutputTray", getPackageName(),
+ R.string.output_tray_second), true)
+ .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
+ | PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
+ PrintAttributes.DUPLEX_MODE_SHORT_EDGE)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_MONOCHROME)
+ .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE
+ | PrintAttributes.FITTING_MODE_NONE,
+ PrintAttributes.FITTING_MODE_FIT_TO_PAGE)
+ .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+ | PrintAttributes.ORIENTATION_LANDSCAPE,
+ PrintAttributes.ORIENTATION_LANDSCAPE)
+ .create();
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ printers.add(printer);
+ addDiscoveredPrinters(printers);
+ }
+
+ private final class MyHandler extends Handler {
+
+ public static final int MESSAGE_ADD_FIRST_FAKE_PRINTER = 1;
+ public static final int MESSAGE_ADD_SECOND_FAKE_PRINTER = 2;
+
+ public MyHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_ADD_FIRST_FAKE_PRINTER: {
+ addFirstFakePrinter();
+ } break;
+ case MESSAGE_ADD_SECOND_FAKE_PRINTER: {
+ addSecondFakePrinter();
+ } break;
+ }
+ }
+ }
+}
diff --git a/PrintService2/src/foo/bar/printservice2/SettingsActivity.java b/PrintService2/src/foo/bar/printservice2/SettingsActivity.java
new file mode 100644
index 0000000..cc197a8
--- /dev/null
+++ b/PrintService2/src/foo/bar/printservice2/SettingsActivity.java
@@ -0,0 +1,15 @@
+package foo.bar.printservice2;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import foo.bar.printservice2.R;
+
+public class SettingsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+}
diff --git a/TestBack/.classpath b/TestBack/.classpath
new file mode 100644
index 0000000..a4763d1
--- /dev/null
+++ b/TestBack/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/TestBack/.project b/TestBack/.project
new file mode 100644
index 0000000..507c2e2
--- /dev/null
+++ b/TestBack/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>TestBack</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/TestBack/Android.mk b/TestBack/Android.mk
new file mode 100644
index 0000000..e8f14e6
--- /dev/null
+++ b/TestBack/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := TestBack
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/TestBack/AndroidManifest.xml b/TestBack/AndroidManifest.xml
new file mode 100644
index 0000000..672f70b
--- /dev/null
+++ b/TestBack/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar.testback"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-permission android:name="android.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE"/>
+ <uses-permission android:name="android.permission.CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"/>
+
+ <uses-sdk
+ android:minSdkVersion="JellyBeanMR2" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:allowBackup="false" >
+ <service
+ android:name=".TestBackService"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService" />
+ </intent-filter>
+ <meta-data
+ android:name="android.accessibilityservice"
+ android:resource="@xml/accessibilityservice" />
+ </service>
+ <receiver
+ android:enabled="true"
+ android:exported="true"
+ android:name=".IdleMaintenanceReceiver">
+ <intent-filter>
+ <action android:name="FOO" />
+ <action android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
+ <action android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
+ </intent-filter>
+ </receiver>
+ </application>
+
+</manifest>
diff --git a/TestBack/res/drawable-hdpi/ic_action_search.png b/TestBack/res/drawable-hdpi/ic_action_search.png
new file mode 100644
index 0000000..67de12d
--- /dev/null
+++ b/TestBack/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/TestBack/res/drawable-hdpi/ic_launcher.png b/TestBack/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a301d57
--- /dev/null
+++ b/TestBack/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/TestBack/res/drawable-ldpi/ic_launcher.png b/TestBack/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 0000000..2c2a58b
--- /dev/null
+++ b/TestBack/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/TestBack/res/drawable-mdpi/ic_action_search.png b/TestBack/res/drawable-mdpi/ic_action_search.png
new file mode 100644
index 0000000..134d549
--- /dev/null
+++ b/TestBack/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/TestBack/res/drawable-mdpi/ic_launcher.png b/TestBack/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f91f736
--- /dev/null
+++ b/TestBack/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/TestBack/res/drawable-xhdpi/ic_action_search.png b/TestBack/res/drawable-xhdpi/ic_action_search.png
new file mode 100644
index 0000000..d699c6b
--- /dev/null
+++ b/TestBack/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/TestBack/res/drawable-xhdpi/ic_launcher.png b/TestBack/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..96095ec
--- /dev/null
+++ b/TestBack/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/TestBack/res/menu/activity_main.xml b/TestBack/res/menu/activity_main.xml
new file mode 100644
index 0000000..cfc10fd
--- /dev/null
+++ b/TestBack/res/menu/activity_main.xml
@@ -0,0 +1,6 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_settings"
+ android:title="@string/menu_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+</menu>
diff --git a/TestBack/res/values-v11/styles.xml b/TestBack/res/values-v11/styles.xml
new file mode 100644
index 0000000..d408cbc
--- /dev/null
+++ b/TestBack/res/values-v11/styles.xml
@@ -0,0 +1,5 @@
+<resources>
+
+ <style name="AppTheme" parent="android:Theme.Holo.Light" />
+
+</resources> \ No newline at end of file
diff --git a/TestBack/res/values-v14/styles.xml b/TestBack/res/values-v14/styles.xml
new file mode 100644
index 0000000..1c089a7
--- /dev/null
+++ b/TestBack/res/values-v14/styles.xml
@@ -0,0 +1,5 @@
+<resources>
+
+ <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+
+</resources> \ No newline at end of file
diff --git a/TestBack/res/values/strings.xml b/TestBack/res/values/strings.xml
new file mode 100644
index 0000000..eefd9b0
--- /dev/null
+++ b/TestBack/res/values/strings.xml
@@ -0,0 +1,8 @@
+<resources>
+
+ <string name="app_name">TestBack</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="menu_settings">Settings</string>
+ <string name="title_activity_main">MainActivity</string>
+
+</resources> \ No newline at end of file
diff --git a/TestBack/res/values/styles.xml b/TestBack/res/values/styles.xml
new file mode 100644
index 0000000..4dba0d0
--- /dev/null
+++ b/TestBack/res/values/styles.xml
@@ -0,0 +1,5 @@
+<resources>
+
+ <style name="AppTheme" parent="android:Theme.Light" />
+
+</resources> \ No newline at end of file
diff --git a/TestBack/res/xml/accessibilityservice.xml b/TestBack/res/xml/accessibilityservice.xml
new file mode 100644
index 0000000..de0613d
--- /dev/null
+++ b/TestBack/res/xml/accessibilityservice.xml
@@ -0,0 +1,5 @@
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accessibilityFeedbackType="feedbackHaptic"
+ android:accessibilityEventTypes="typeAllMask"
+ android:canRetrieveWindowContent="true"
+/>
diff --git a/TestBack/src/foo/bar/testback/Foo.java b/TestBack/src/foo/bar/testback/Foo.java
new file mode 100644
index 0000000..6fcbf1a
--- /dev/null
+++ b/TestBack/src/foo/bar/testback/Foo.java
@@ -0,0 +1,45 @@
+package foo.bar.testback;
+
+public class Foo {
+
+ private Object mValue;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mValue == null) ? 0 : mValue.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Foo other = (Foo) obj;
+ if (mValue == null) {
+ if (other.mValue != null)
+ return false;
+ } else if (!mValue.equals(other.mValue))
+ return false;
+ return true;
+ }
+
+
+ private class Bar {
+ protected void doSomething() {
+
+ }
+ }
+
+ private class Baz extends Bar {
+ @Override
+ protected void doSomething() {
+
+ }
+ }
+}
diff --git a/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java b/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java
new file mode 100644
index 0000000..d3f1266
--- /dev/null
+++ b/TestBack/src/foo/bar/testback/IdleMaintenanceReceiver.java
@@ -0,0 +1,18 @@
+package foo.bar.testback;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Debug;
+import android.util.Log;
+
+public class IdleMaintenanceReceiver extends BroadcastReceiver {
+
+ private static final String LOG_TAG = IdleMaintenanceReceiver.class.getSimpleName();
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Debug.waitForDebugger();
+ Log.i(LOG_TAG, (intent.getAction() != null) ? intent.getAction() : "null");
+ }
+}
diff --git a/TestBack/src/foo/bar/testback/TestBackService.java b/TestBack/src/foo/bar/testback/TestBackService.java
new file mode 100644
index 0000000..bb47621
--- /dev/null
+++ b/TestBack/src/foo/bar/testback/TestBackService.java
@@ -0,0 +1,145 @@
+package foo.bar.testback;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+public class TestBackService extends AccessibilityService {
+
+ private static final String LOG_TAG = TestBackService.class.getSimpleName();
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ AccessibilityManager am = (AccessibilityManager)
+ getSystemService(ACCESSIBILITY_SERVICE);
+ Log.i(LOG_TAG, "accessibilityEnabled: " + am.isEnabled()
+ + " touchExplorationEnabled: " + am.isTouchExplorationEnabled());
+// AccessibilityServiceInfo info = getServiceInfo();
+// if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) == 0) {
+// info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+// } else {
+// info.flags &= ~AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+// }
+// setServiceInfo(info);
+ sendEmptyMessageDelayed(0, 20000);
+ }
+ };
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+// Log.i(LOG_TAG, AccessibilityEvent.eventTypeToString(event.getEventType()));
+ }
+
+ @Override
+ protected boolean onGesture(int gestureId) {
+ switch (gestureId) {
+ case AccessibilityService.GESTURE_SWIPE_DOWN: {
+ dumpIdResNames(getRootInActiveWindow());
+ } break;
+ // COPY
+ case AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT: {
+ AccessibilityNodeInfo root = getRootInActiveWindow();
+ if (root != null) {
+ AccessibilityNodeInfo focus = root.findFocus(
+ AccessibilityNodeInfo.FOCUS_INPUT);
+ if (focus != null) {
+ if ((focus.getActions() & 0x00004000) /* COPY*/ != 0) {
+ final boolean performed = focus.performAction(0x00004000);
+ Log.i(LOG_TAG, "Performed: " + performed);
+ }
+ focus.recycle();
+ }
+ root.recycle();
+ }
+ } break;
+ // PASTE
+ case AccessibilityService.GESTURE_SWIPE_UP: {
+ AccessibilityNodeInfo root = getRootInActiveWindow();
+ if (root != null) {
+ AccessibilityNodeInfo focus = root.findFocus(
+ AccessibilityNodeInfo.FOCUS_INPUT);
+ if (focus != null) {
+ if ((focus.getActions() & 0x00008000) /* PASTE*/ != 0) {
+ final boolean performed = focus.performAction(0x00008000);
+ Log.i(LOG_TAG, "Performed: " + performed);
+ }
+ focus.recycle();
+ }
+ root.recycle();
+ }
+ } break;
+ // CUT
+ case AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT: {
+ AccessibilityNodeInfo root = getRootInActiveWindow();
+ if (root != null) {
+ AccessibilityNodeInfo focus = root.findFocus(
+ AccessibilityNodeInfo.FOCUS_INPUT);
+ if (focus != null) {
+ if ((focus.getActions() & 0x00010000) /* CUT*/ != 0) {
+ final boolean performed = focus.performAction(0x00010000);
+ Log.i(LOG_TAG, "Performed: " + performed);
+ }
+ focus.recycle();
+ }
+ root.recycle();
+ }
+ } break;
+ // SELECT_ALL
+ case AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP: {
+ AccessibilityNodeInfo root = getRootInActiveWindow();
+ if (root != null) {
+ AccessibilityNodeInfo focus = root.findFocus(
+ AccessibilityNodeInfo.FOCUS_INPUT);
+ if (focus != null) {
+ if ((focus.getActions() & 0x00020000) /* SELECT ALL*/ != 0) {
+ final boolean performed = focus.performAction(0x00020000);
+ Log.i(LOG_TAG, "Performed: " + performed);
+ }
+ focus.recycle();
+ }
+ root.recycle();
+ }
+ } break;
+ }
+ return super.onGesture(gestureId);
+ }
+
+ @Override
+ public boolean onKeyEvent(KeyEvent event) {
+ Log.i(LOG_TAG, "onKeyEvent: " + event);
+ boolean result = false;
+ return result;
+ }
+
+ private void dumpIdResNames(AccessibilityNodeInfo root) {
+ if (root == null) {
+ return;
+ }
+ if (root.getViewIdResourceName() != null) {
+ Log.i(LOG_TAG, root.getViewIdResourceName().toString());
+ }
+ final int childCount = root.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ dumpIdResNames(root.getChild(i));
+ }
+ }
+
+ @Override
+ public void onInterrupt() {
+ /* ignore */
+ }
+
+ @Override
+ public void onServiceConnected() {
+// AccessibilityServiceInfo info = getServiceInfo();
+// info.flags |= AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
+// setServiceInfo(info);
+ }
+}