Add initial support for Vision Barcode API

This work is heavily based on work by @lfxgroove

Co-Authored-By: lfxgroove <lfxgroove@zoho.com>
This commit is contained in:
Marvin W 2020-12-05 01:36:12 +01:00
parent 2b09a5e530
commit 5e39818a20
No known key found for this signature in database
GPG Key ID: 072E9235DB996F2A
28 changed files with 1233 additions and 9 deletions

View File

@ -14,9 +14,6 @@
* limitations under the License.
*/
package org.microg.gms.kotlin
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.ObjectWrapper
package com.google.android.gms.dynamic
inline fun <reified T> IObjectWrapper?.unwrap(): T? = ObjectWrapper.unwrapTyped(this, T::class.java)

View File

@ -45,6 +45,7 @@ dependencies {
implementation project(':play-services-base-core-ui')
implementation project(':play-services-conscrypt-provider-core')
implementation project(':play-services-location-core')
implementation project(':play-services-vision-core')
withNearbyImplementation project(':play-services-nearby-core')
withNearbyImplementation project(':play-services-nearby-core-ui')
implementation project(':play-services-core-proto')

View File

@ -28,12 +28,14 @@ import com.google.android.gms.dynamite.IDynamiteLoader;
import org.microg.gms.common.Constants;
import java.lang.reflect.Field;
public class DynamiteLoaderImpl extends IDynamiteLoader.Stub {
private static final String TAG = "GmsDynamiteLoaderImpl";
@Override
public IObjectWrapper createModuleContext(IObjectWrapper wrappedContext, String moduleId, int minVersion) throws RemoteException {
Log.d(TAG, "unimplemented Method: createModuleContext for " + moduleId + " at version " + minVersion + ", returning gms context");
Log.d(TAG, "createModuleContext for " + moduleId + " at version " + minVersion);
final Context context = (Context) ObjectWrapper.unwrap(wrappedContext);
try {
return ObjectWrapper.wrap(new ContextWrapper(context.createPackageContext(Constants.GMS_PACKAGE_NAME, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY)) {
@ -55,6 +57,12 @@ public class DynamiteLoaderImpl extends IDynamiteLoader.Stub {
@Override
public int getModuleVersion2(IObjectWrapper context, String moduleId, boolean updateConfigIfRequired) throws RemoteException {
try {
return Class.forName("com.google.android.gms.dynamite.descriptors." + moduleId + ".ModuleDescriptor").getDeclaredField("MODULE_VERSION").getInt(null);
} catch (Exception e) {
Log.w(TAG, "No such module known: " + moduleId);
}
if (moduleId.equals("com.google.android.gms.firebase_database")) {
Log.d(TAG, "returning temp fix module version for " + moduleId + ". Firebase Database will not be functional!");
return com.google.android.gms.dynamite.descriptors.com.google.android.gms.firebase_database.ModuleDescriptor.MODULE_VERSION;

View File

@ -50,7 +50,7 @@ import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.plugins.annotation.*
import com.mapbox.mapboxsdk.plugins.annotation.Annotation
import com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_ROUND
import org.microg.gms.kotlin.unwrap
import com.google.android.gms.dynamic.unwrap
import org.microg.gms.maps.MapsConstants.*
import org.microg.gms.maps.mapbox.model.*
import org.microg.gms.maps.mapbox.utils.MapContext

View File

@ -25,7 +25,7 @@ import com.google.android.gms.maps.internal.IProjectionDelegate
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.VisibleRegion
import com.mapbox.mapboxsdk.maps.Projection
import org.microg.gms.kotlin.unwrap
import com.google.android.gms.dynamic.unwrap
import org.microg.gms.maps.mapbox.utils.toGms
import org.microg.gms.maps.mapbox.utils.toMapbox
import kotlin.math.roundToInt
@ -77,4 +77,4 @@ class ProjectionImpl(private val projection: Projection, private val withoutTilt
companion object {
private val TAG = "GmsMapProjection"
}
}
}

View File

@ -26,7 +26,7 @@ import com.google.android.gms.maps.model.internal.IMarkerDelegate
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
import com.mapbox.mapboxsdk.plugins.annotation.Symbol
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
import org.microg.gms.kotlin.unwrap
import com.google.android.gms.dynamic.unwrap
import org.microg.gms.maps.mapbox.GoogleMapImpl
import org.microg.gms.maps.mapbox.utils.toMapbox

View File

@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
android {
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
apply from: '../gradle/publish-android.gradle'
description = 'microG API for play-services-vision'
dependencies {
api project(':play-services-basement')
api project(':play-services-base-api')
implementation "androidx.annotation:annotation:$annotationVersion"
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest package="org.microg.gms.vision.api"/>

View File

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode;
parcelable Barcode;

View File

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode.internal.client;
parcelable BarcodeDetectorOptions;

View File

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode.internal.client;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.internal.client.BarcodeDetectorOptions;
import com.google.android.gms.vision.internal.FrameMetadataParcel;
import com.google.android.gms.dynamic.IObjectWrapper;
interface INativeBarcodeDetector {
Barcode[] detectBytes(IObjectWrapper byteBuffer, in FrameMetadataParcel metadata) = 0;
Barcode[] detectBitmap(IObjectWrapper bitmap, in FrameMetadataParcel metadata) = 1;
void close() = 2;
}

View File

@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode.internal.client;
import com.google.android.gms.vision.barcode.internal.client.BarcodeDetectorOptions;
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetector;
import com.google.android.gms.dynamic.IObjectWrapper;
interface INativeBarcodeDetectorCreator {
INativeBarcodeDetector create(IObjectWrapper context, in BarcodeDetectorOptions options) = 0;
}

View File

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.internal;
parcelable FrameMetadataParcel;

View File

@ -0,0 +1,593 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
* Notice: Portions of this file are reproduced from work created and shared by Google and used
* according to terms described in the Creative Commons 4.0 Attribution License.
* See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.vision.barcode;
import android.graphics.Point;
import android.graphics.Rect;
import androidx.annotation.Nullable;
import org.microg.gms.common.PublicApi;
import org.microg.safeparcel.AutoSafeParcelable;
/**
* Barcode represents a single recognized barcode and its value.
* <p>
* The barcode's raw, unmodified, and uninterpreted content is returned in the {@link #rawValue} field, while the barcode type (i.e. its encoding) can be found in the {@link #format} field.
* <p>
* Barcodes that contain structured data (commonly done with QR codes) are parsed and iff valid, the {@link #valueFormat} field is set to one of the value format constants (e.g. {@link #GEO}) and the corresponding field is set (e.g. {@link #geoPoint}).
*/
@PublicApi
public class Barcode extends AutoSafeParcelable {
/**
* Barcode value format constant for contact information.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int CONTACT_INFO = 1;
/**
* Barcode value format constant for email message details.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int EMAIL = 2;
/**
* Barcode value format constant for ISBNs.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int ISBN = 3;
/**
* Barcode value format constant for phone numbers.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int PHONE = 4;
/**
* Barcode value format constant for product codes.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int PRODUCT = 5;
/**
* Barcode value format constant for SMS details.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int SMS = 6;
/**
* Barcode value format constant for plain text.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int TEXT = 7;
/**
* Barcode value format constant for URLs/bookmarks.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int URL = 8;
/**
* Barcode value format constant for WiFi access point details.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int WIFI = 9;
/**
* Barcode value format constant for geographic coordinates.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int GEO = 10;
/**
* Barcode value format constant for calendar events.
* Specifies the format of a Barcode value via the {@link #valueFormat} field.
*/
public static final int CALENDAR_EVENT = 11;
public static final int DRIVER_LICENSE = 12;
/**
* Barcode format constant representing the union of all supported formats.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize.
* This is also the default setting.
*/
public static final int ALL_FORMATS = 0;
/**
* Barcode format constant for Code 128.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int CODE_128 = 1;
/**
* Barcode format constant for Code 39.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int CODE_39 = 2;
/**
* Barcode format constant for Code 93.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int CODE_93 = 4;
/**
* Barcode format constant for Codebar.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int CODABAR = 8;
/**
* Barcode format constant for Data Matrix.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int DATA_MATRIX = 16;
/**
* Barcode format constant for EAN-13.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int EAN_13 = 32;
/**
* Barcode format constant for EAN-8.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int EAN_8 = 64;
/**
* Barcode format constant for ITF (Interleaved Two-of-Five).
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int ITF = 128;
/**
* Barcode format constant for QR Code.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int QR_CODE = 256;
/**
* Barcode format constant for UPC-A.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int UPC_A = 512;
/**
* Barcode format constant for UPC-E.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int UPC_E = 1024;
/**
* Barcode format constant for PDF-417.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int PDF417 = 2048;
/**
* Barcode format constant for AZTEC.
* Pass into {@link BarcodeDetector.Builder#setBarcodeFormats(int)} to select formats to recognize,
* and also specifies a detected Barcode's {@link #format} via the format field.
*/
public static final int AZTEC = 4096;
@Field(1)
private final int versionCode = 1;
/**
* Barcode format, for example {@link #EAN_13}.
* <p>
* Note that this field may contain values not present in the current set of format constants.
* When mapping this value to something else, it is advisable to have a default/fallback case.
*/
@Field(2)
public int format;
/**
* Barcode value as it was encoded in the barcode. Structured values are not parsed, for example: 'MEBKM:TITLE:Google;URL://www.google.com;;' Does not include the supplement value.
*/
@Field(3)
public String rawValue;
/**
* Barcode value in a user-friendly format.
* May omit some of the information encoded in the barcode.
* For example, in the case above the display_value might be '//www.google.com'.
* If {@link #valueFormat}=={@link #TEXT}, this field will be equal to {@link #rawValue}.
* This value may be multiline, for example, when line breaks are encoded into the original {@link #TEXT} barcode value.
* May include the supplement value.
*/
@Field(4)
public String displayValue;
/**
* Format of the barcode value. For example, {@link #TEXT}, {@link #PRODUCT}, {@link #URL}, etc.
* <p>
* Note that this field may contain values not present in the current set of value format constants.
* When mapping this value to something else, it is advisable to have a default/fallback case.
*/
@Field(5)
public int valueFormat;
/**
* 4 corner points in clockwise direction starting with top-left.
* Due to the possible perspective distortions, this is not necessarily a rectangle.
*/
@Field(6)
public Point[] cornerPoints;
/**
* Parsed email details (set iff {@link #valueFormat} is {@link #EMAIL}).
*/
@Nullable
@Field(7)
public Barcode.Email email;
/**
* Parsed phone details (set iff {@link #valueFormat} is {@link #PHONE}).
*/
@Nullable
@Field(8)
public Barcode.Phone phone;
/**
* Parsed SMS details (set iff {@link #valueFormat} is {@link #SMS}).
*/
@Nullable
@Field(9)
public Barcode.Sms sms;
/**
* Parsed WiFi AP details (set iff {@link #valueFormat} is {@link #WIFI}).
*/
@Nullable
@Field(10)
public Barcode.WiFi wifi;
/**
* Parsed URL bookmark details (set iff {@link #valueFormat} is {@link #URL}).
*/
@Nullable
@Field(11)
public Barcode.UrlBookmark url;
/**
* Parsed geo coordinates (set iff {@link #valueFormat} is {@link #GEO}).
*/
@Nullable
@Field(12)
public Barcode.GeoPoint geoPoint;
/**
* Parsed calendar event details (set iff {@link #valueFormat} is {@link #CALENDAR_EVENT}).
*/
@Nullable
@Field(13)
public Barcode.CalendarEvent calendarEvent;
/**
* Parsed contact details (set iff {@link #valueFormat} is {@link #CONTACT_INFO}).
*/
@Nullable
@Field(14)
public Barcode.ContactInfo contactInfo;
/**
* Parsed driver's license details (set iff {@link #valueFormat} is {@link #DRIVER_LICENSE}).
*/
@Nullable
@Field(15)
public Barcode.DriverLicense driverLicense;
/**
* Barcode value as it was encoded in the barcode as byte array.
*/
@Field(16)
public byte[] rawBytes;
/**
* If outputUnrecognizedBarcodes is set, isRecognized can be set to false to indicate failure in decoding the detected barcode.
*/
@Field(17)
public boolean isRecognized;
/**
* Returns the barcode's axis-aligned bounding box.
*/
public Rect getBoundingBox() {
int left = Integer.MAX_VALUE, top = Integer.MIN_VALUE, right = Integer.MIN_VALUE, bottom = Integer.MAX_VALUE;
for (Point point : cornerPoints) {
left = Math.min(left, point.x);
top = Math.max(top, point.y);
right = Math.max(right, point.x);
bottom = Math.min(bottom, point.y);
}
return new Rect(left, top, right, bottom);
}
/**
* An address.
*/
public static class Address extends AutoSafeParcelable {
/**
* Address type.
*/
public static final int UNKNOWN = 0;
public static final int WORK = 1;
public static final int HOME = 2;
@Field(1)
private int versionCode = 1;
@Field(2)
public int type;
/**
* Formatted address, multiple lines when appropriate. This field always contains at least one line.
*/
@Field(3)
public String[] addressLines;
public static Creator<Address> CREATOR = new AutoCreator<>(Address.class);
}
/**
* DateTime data type used in calendar events. If hours/minutes/seconds are not specified in the barcode value, they will be set to -1.
*/
public static class CalendarDateTime extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public int year;
@Field(3)
public int month;
@Field(4)
public int day;
@Field(5)
public int hours;
@Field(6)
public int minutes;
@Field(7)
public int seconds;
@Field(8)
public boolean isUtc;
@Field(9)
public String rawValue;
public static Creator<CalendarDateTime> CREATOR = new AutoCreator<>(CalendarDateTime.class);
}
/**
* A calendar event extracted from QRCode.
*/
public static class CalendarEvent extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public String summary;
@Field(3)
public String description;
@Field(4)
public String location;
@Field(5)
public String organizer;
@Field(6)
public String status;
@Field(7)
public Barcode.CalendarDateTime start;
@Field(8)
public Barcode.CalendarDateTime end;
public static Creator<CalendarEvent> CREATOR = new AutoCreator<>(CalendarEvent.class);
}
/**
* A person's or organization's business card. For example a VCARD.
*/
public static class ContactInfo extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public Barcode.PersonName name;
@Field(3)
public String organization;
@Field(4)
public String title;
@Field(5)
public Barcode.Phone[] phones;
@Field(6)
public Barcode.Email[] emails;
@Field(7)
public String[] urls;
@Field(8)
public Barcode.Address[] addresses;
public static Creator<ContactInfo> CREATOR = new AutoCreator<>(ContactInfo.class);
}
/**
* A driver license or ID card.
*/
public static class DriverLicense extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
/**
* "DL" for driver licenses, "ID" for ID cards.
*/
@Field(2)
public String documentType;
/**
* Holder's first name.
*/
@Field(3)
public String firstName;
@Field(4)
public String middleName;
@Field(5)
public String lastName;
/**
* Gender. 1 - male, 2 - female.
*/
@Field(6)
public String gender;
/**
* Holder's street address.
*/
@Field(7)
public String addressStreet;
@Field(8)
public String addressCity;
@Field(9)
public String addressState;
@Field(10)
public String addressZip;
/**
* Driver license ID number.
*/
@Field(11)
public String licenseNumber;
/**
* The date format depends on the issuing country. MMDDYYYY for the US, YYYYMMDD for Canada.
*/
@Field(12)
public String issueDate;
@Field(13)
public String expiryDate;
@Field(14)
public String birthDate;
/**
* Country in which DL/ID was issued. US = "USA", Canada = "CAN".
*/
@Field(15)
public String issuingCountry;
public static Creator<DriverLicense> CREATOR = new AutoCreator<>(DriverLicense.class);
}
/**
* An email message from a 'MAILTO:' or similar QRCode type.
*/
public static class Email extends AutoSafeParcelable {
/**
* Email type.
*/
public static final int UNKNOWN = 0;
public static final int WORK = 1;
public static final int HOME = 2;
@Field(1)
private int versionCode = 1;
@Field(2)
public int type;
@Field(3)
public String address;
@Field(4)
public String subject;
@Field(5)
public String body;
public static Creator<Email> CREATOR = new AutoCreator<>(Email.class);
}
/**
* GPS coordinates from a 'GEO:' or similar QRCode type.
*/
public static class GeoPoint extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public double lat;
@Field(3)
public double lng;
public static Creator<GeoPoint> CREATOR = new AutoCreator<>(GeoPoint.class);
}
/**
* A person's name, both formatted version and individual name components.
*/
public static class PersonName extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
/**
* Properly formatted name.
*/
@Field(2)
public String formattedName;
/**
* Designates a text string to be set as the kana name in the phonebook. Used for Japanese contacts.
*/
@Field(3)
public String pronunciation;
@Field(4)
public String prefix;
@Field(5)
public String first;
@Field(6)
public String middle;
@Field(7)
public String last;
@Field(8)
public String suffix;
public static Creator<PersonName> CREATOR = new AutoCreator<>(PersonName.class);
}
/**
* A phone number from a 'TEL:' or similar QRCode type.
*/
public static class Phone extends AutoSafeParcelable {
/**
* Phone type.
*/
public static final int UNKNOWN = 0;
public static final int WORK = 1;
public static final int HOME = 2;
public static final int FAX = 3;
public static final int MOBILE = 4;
@Field(1)
private int versionCode = 1;
@Field(2)
public int type;
@Field(3)
public String number;
public static Creator<Phone> CREATOR = new AutoCreator<>(Phone.class);
}
/**
* An sms message from an 'SMS:' or similar QRCode type.
*/
public static class Sms extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public String message;
@Field(3)
public String phoneNumber;
public static Creator<Sms> CREATOR = new AutoCreator<>(Sms.class);
}
/**
* A URL and title from a 'MEBKM:' or similar QRCode type.
*/
public static class UrlBookmark extends AutoSafeParcelable {
@Field(1)
private int versionCode = 1;
@Field(2)
public String title;
/**
* Bookmark URL. Note that some common errors may be corrected here. For example, "http//...", "http:...", etc. will be replaced with "//".
*/
@Field(3)
public String url;
public static Creator<UrlBookmark> CREATOR = new AutoCreator<>(UrlBookmark.class);
}
/**
* A wifi network parameters from a 'WIFI:' or similar QRCode type.
*/
public static class WiFi extends AutoSafeParcelable {
/**
* WiFi encryption type.
*/
public static final int OPEN = 1;
public static final int WPA = 2;
public static final int WEP = 3;
@Field(1)
private int versionCode = 1;
@Field(2)
public String ssid;
@Nullable
@Field(3)
public String password;
@Field(4)
public int encryptionType;
public static Creator<WiFi> CREATOR = new AutoCreator<>(WiFi.class);
}
public static final Creator<Barcode> CREATOR = new AutoCreator<>(Barcode.class);
}

View File

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode.internal.client;
import org.microg.safeparcel.AutoSafeParcelable;
public class BarcodeDetectorOptions extends AutoSafeParcelable {
@Field(1)
public int versionCode = 1;
@Field(2)
public int formats;
public static Creator<BarcodeDetectorOptions> CREATOR = new AutoCreator<>(BarcodeDetectorOptions.class);
}

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.internal;
import org.microg.safeparcel.AutoSafeParcelable;
public class FrameMetadataParcel extends AutoSafeParcelable {
@Field(1)
private final int versionCode = 1;
@Field(2)
public int width;
@Field(3)
public int height;
@Field(4)
public int id;
@Field(5)
public long timestampMillis;
@Field(6)
public int rotation;
public static Creator<FrameMetadataParcel> CREATOR = new AutoCreator<>(FrameMetadataParcel.class);
}

View File

@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'maven-publish'
apply plugin: 'signing'
dependencies {
api project(':play-services-vision-api')
implementation project(':play-services-base-core')
implementation "androidx.annotation:annotation:$annotationVersion"
implementation 'com.google.zxing:core:3.4.1'
}
android {
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
sourceSets {
main {
java.srcDirs += 'src/main/kotlin'
}
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
apply from: '../gradle/publish-android.gradle'
description = 'microG service implementation for play-services-vision'

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.microg.gms.vision.core">
<application>
</application>
</manifest>

View File

@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.dynamite.descriptors.com.google.android.gms.vision.barcode;
public class ModuleDescriptor {
public static final String MODULE_ID = "com.google.android.gms.vision.barcode";
public static final int MODULE_VERSION = 1;
}

View File

@ -0,0 +1,11 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.dynamite.descriptors.com.google.android.gms.vision.dynamite;
public class ModuleDescriptor {
public static final String MODULE_ID = "com.google.android.gms.vision.dynamite";
public static final int MODULE_VERSION = 1;
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.barcode
import android.content.Context
import androidx.annotation.Keep
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.vision.barcode.internal.client.BarcodeDetectorOptions
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetector
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetectorCreator
import com.google.android.gms.dynamic.unwrap
import org.microg.gms.vision.barcode.BarcodeDetector
@Keep
class ChimeraNativeBarcodeDetectorCreator : INativeBarcodeDetectorCreator.Stub() {
override fun create(context: IObjectWrapper, options: BarcodeDetectorOptions): INativeBarcodeDetector {
return BarcodeDetector(context.unwrap<Context>()!!, options)
}
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package com.google.android.gms.vision.client
import android.content.Context
import androidx.annotation.Keep
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.unwrap
import com.google.android.gms.vision.barcode.internal.client.BarcodeDetectorOptions
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetector
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetectorCreator
import org.microg.gms.vision.barcode.BarcodeDetector
@Keep
class ChimeraNativeBarcodeDetectorCreator : INativeBarcodeDetectorCreator.Stub() {
override fun create(context: IObjectWrapper, options: BarcodeDetectorOptions): INativeBarcodeDetector {
return BarcodeDetector(context.unwrap<Context>()!!, options)
}
}

View File

@ -0,0 +1,100 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.vision.barcode
import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.unwrap
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.internal.client.BarcodeDetectorOptions
import com.google.android.gms.vision.barcode.internal.client.INativeBarcodeDetector
import com.google.android.gms.vision.internal.FrameMetadataParcel
import com.google.zxing.*
import com.google.zxing.aztec.AztecReader
import com.google.zxing.common.HybridBinarizer
import com.google.zxing.datamatrix.DataMatrixReader
import com.google.zxing.multi.MultipleBarcodeReader
import com.google.zxing.multi.qrcode.QRCodeMultiReader
import com.google.zxing.oned.*
import com.google.zxing.pdf417.PDF417Reader
import java.nio.ByteBuffer
import java.nio.IntBuffer
private const val TAG = "GmsVisionBarcode"
class BarcodeDetector(val context: Context, val options: BarcodeDetectorOptions) : INativeBarcodeDetector.Stub() {
override fun detectBitmap(wrappedBitmap: IObjectWrapper, metadata: FrameMetadataParcel): Array<Barcode> {
val bitmap = wrappedBitmap.unwrap<Bitmap>() ?: return emptyArray()
val frameBuf: IntBuffer = IntBuffer.allocate(bitmap.byteCount)
bitmap.copyPixelsToBuffer(frameBuf)
return detectFromSource(RGBLuminanceSource(metadata.width, metadata.height, frameBuf.array()))
}
override fun detectBytes(wrappedByteBuffer: IObjectWrapper, metadata: FrameMetadataParcel): Array<Barcode> {
return detectFromSource(DirectLuminanceSource(metadata.width, metadata.height, wrappedByteBuffer.unwrap<ByteBuffer>()
?: return emptyArray()))
}
private fun mayDecodeType(image: BinaryBitmap, type: Int, reader: () -> Reader): List<Barcode> {
return if ((options.formats and type) != 0 || options.formats == Barcode.ALL_FORMATS) {
reader().run {
try {
if (this is MultipleBarcodeReader) {
decodeMultiple(image).map { it.toGms() }
} else {
listOf(decode(image).toGms())
}
} catch (e: NotFoundException) {
emptyList<Barcode>()
} catch (e: FormatException) {
emptyList<Barcode>()
} catch (e: ChecksumException) {
emptyList<Barcode>()
} catch (e: Exception) {
Log.w(TAG, "Exception with $this: $e")
emptyList<Barcode>()
}
}
} else {
emptyList()
}
}
private fun detectFromImage(image: BinaryBitmap, results: MutableList<Barcode>): Int {
var resultsSize = results.size
results.addAll(mayDecodeType(image, Barcode.CODE_128) { Code128Reader() })
results.addAll(mayDecodeType(image, Barcode.CODE_39) { Code39Reader() })
results.addAll(mayDecodeType(image, Barcode.CODABAR) { CodaBarReader() })
results.addAll(mayDecodeType(image, Barcode.DATA_MATRIX) { DataMatrixReader() })
results.addAll(mayDecodeType(image, Barcode.EAN_13) { EAN13Reader() })
results.addAll(mayDecodeType(image, Barcode.EAN_8) { EAN8Reader() })
results.addAll(mayDecodeType(image, Barcode.ITF) { ITFReader() })
results.addAll(mayDecodeType(image, Barcode.QR_CODE) { QRCodeMultiReader() })
results.addAll(mayDecodeType(image, Barcode.UPC_A) { UPCAReader() })
results.addAll(mayDecodeType(image, Barcode.UPC_E) { UPCEReader() })
results.addAll(mayDecodeType(image, Barcode.PDF417) { PDF417Reader() })
results.addAll(mayDecodeType(image, Barcode.AZTEC) { AztecReader() })
return results.size - resultsSize
}
private fun detectFromSource(source: LuminanceSource): Array<Barcode> {
val results = arrayListOf<Barcode>()
try {
detectFromImage(BinaryBitmap(HybridBinarizer(source)), results)
detectFromImage(BinaryBitmap(HybridBinarizer(source.invert())), results)
} catch (e: Exception) {
Log.w(TAG, e)
}
return results.distinctBy { it.rawValue }.toTypedArray()
}
override fun close() {
Log.d(TAG, "close()")
}
}

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.vision.barcode
import com.google.zxing.LuminanceSource
import java.nio.ByteBuffer
class DirectLuminanceSource(width: Int, height: Int, val bytes: ByteBuffer) : LuminanceSource(width, height) {
override fun getRow(y: Int, row: ByteArray?): ByteArray {
val row = row?.takeIf { it.size >= width } ?: ByteArray(width)
bytes.position(width * y)
bytes.get(row, 0, width)
return row
}
override fun getMatrix(): ByteArray {
return bytes.array()
}
}

View File

@ -0,0 +1,200 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.vision.barcode
import android.graphics.Point
import com.google.android.gms.vision.barcode.Barcode
import com.google.zxing.BarcodeFormat
import com.google.zxing.Result
import com.google.zxing.ResultPoint
import com.google.zxing.client.result.*
import java.util.*
fun BarcodeFormat.toGms(): Int = when (this) {
BarcodeFormat.AZTEC -> Barcode.AZTEC
BarcodeFormat.CODABAR -> Barcode.CODABAR
BarcodeFormat.CODE_128 -> Barcode.CODE_128
BarcodeFormat.CODE_39 -> Barcode.CODE_39
BarcodeFormat.CODE_93 -> Barcode.CODE_93
BarcodeFormat.DATA_MATRIX -> Barcode.DATA_MATRIX
BarcodeFormat.EAN_13 -> Barcode.EAN_13
BarcodeFormat.EAN_8 -> Barcode.EAN_8
BarcodeFormat.ITF -> Barcode.ITF
BarcodeFormat.PDF_417 -> Barcode.PDF417
BarcodeFormat.QR_CODE -> Barcode.QR_CODE
BarcodeFormat.UPC_A -> Barcode.UPC_A
BarcodeFormat.UPC_E -> Barcode.UPC_E
else -> Barcode.ALL_FORMATS
}
fun ParsedResultType.toGms(): Int = when (this) {
ParsedResultType.ADDRESSBOOK -> Barcode.CONTACT_INFO
ParsedResultType.CALENDAR -> Barcode.CALENDAR_EVENT
ParsedResultType.EMAIL_ADDRESS -> Barcode.EMAIL
ParsedResultType.GEO -> Barcode.GEO
ParsedResultType.ISBN -> Barcode.ISBN
ParsedResultType.PRODUCT -> Barcode.PRODUCT
ParsedResultType.SMS -> Barcode.SMS
ParsedResultType.TEL -> Barcode.PHONE
ParsedResultType.TEXT -> Barcode.TEXT
ParsedResultType.URI -> Barcode.URL
ParsedResultType.WIFI -> Barcode.WIFI
else -> Barcode.TEXT
}
fun AddressBookParsedResult.toGms(): Barcode.ContactInfo {
val contactInfo = Barcode.ContactInfo()
// TODO: contactInfo.name
contactInfo.organization = org
contactInfo.title = title
contactInfo.phones = phoneNumbers.orEmpty().mapIndexed { i, a ->
Barcode.Phone().apply {
type = when (phoneTypes?.getOrNull(i)) {
"WORK" -> Barcode.Phone.WORK
"HOME" -> Barcode.Phone.HOME
"FAX" -> Barcode.Phone.FAX
"MOBILE" -> Barcode.Phone.MOBILE
else -> Barcode.Phone.UNKNOWN
}
number = a
}
}.toTypedArray()
contactInfo.emails = emails.orEmpty().mapIndexed { i, a ->
Barcode.Email().apply {
type = when (emailTypes?.getOrNull(i)) {
"WORK" -> Barcode.Email.WORK
"HOME" -> Barcode.Email.HOME
else -> Barcode.Email.UNKNOWN
}
address = a
}
}.toTypedArray()
contactInfo.urls = urLs
contactInfo.addresses = addresses.orEmpty().mapIndexed { i, a ->
Barcode.Address().apply {
type = when (addressTypes?.getOrNull(i)) {
"WORK" -> Barcode.Address.WORK
"HOME" -> Barcode.Address.HOME
else -> Barcode.Address.UNKNOWN
}
addressLines = a.split("\n").toTypedArray()
}
}.toTypedArray()
return contactInfo
}
fun CalendarParsedResult.toGms(): Barcode.CalendarEvent {
fun createDateTime(timestamp: Long, isAllDay: Boolean) = Barcode.CalendarDateTime().apply {
val calendar = Calendar.getInstance()
calendar.time = Date(timestamp)
year = calendar.get(Calendar.YEAR)
month = calendar.get(Calendar.MONTH)
day = calendar.get(Calendar.DAY_OF_MONTH)
if (isAllDay) {
hours = -1
minutes = -1
seconds = -1
} else {
hours = calendar.get(Calendar.HOUR_OF_DAY)
minutes = calendar.get(Calendar.MINUTE)
seconds = calendar.get(Calendar.SECOND)
}
}
val event = Barcode.CalendarEvent()
event.summary = summary
event.description = description
event.location = location
event.organizer = organizer
event.start = createDateTime(startTimestamp, isStartAllDay)
event.end = createDateTime(endTimestamp, isEndAllDay)
return event
}
fun EmailAddressParsedResult.toGms(): Barcode.Email {
val email = Barcode.Email()
email.address = tos?.getOrNull(0)
email.subject = subject
email.body = body
return email
}
fun GeoParsedResult.toGms(): Barcode.GeoPoint {
val geo = Barcode.GeoPoint()
geo.lat = latitude
geo.lng = longitude
return geo
}
fun TelParsedResult.toGms(): Barcode.Phone {
val phone = Barcode.Phone()
phone.number = number
return phone
}
fun SMSParsedResult.toGms(): Barcode.Sms {
val sms = Barcode.Sms()
sms.message = body
sms.phoneNumber = numbers?.getOrNull(0)
return sms
}
fun WifiParsedResult.toGms(): Barcode.WiFi {
val wifi = Barcode.WiFi()
wifi.ssid = ssid
wifi.password = password
wifi.encryptionType = when (networkEncryption) {
"OPEN" -> Barcode.WiFi.OPEN
"WEP" -> Barcode.WiFi.WEP
"WPA" -> Barcode.WiFi.WPA
"WPA2" -> Barcode.WiFi.WPA
else -> 0
}
return wifi
}
fun URIParsedResult.toGms(): Barcode.UrlBookmark {
val url = Barcode.UrlBookmark()
url.url = uri
url.title = title
return url
}
fun ResultPoint.toPoint(): Point = Point(x.toInt(), y.toInt())
fun Result.toGms(): Barcode {
val barcode = Barcode()
barcode.format = barcodeFormat.toGms()
barcode.rawBytes = rawBytes
barcode.rawValue = text
barcode.cornerPoints = resultPoints.map { it.toPoint() }.toTypedArray()
val parsed = ResultParser.parseResult(this)
barcode.displayValue = parsed.displayResult
barcode.valueFormat = parsed.type.toGms()
when (parsed) {
is EmailAddressParsedResult ->
barcode.email = parsed.toGms()
is TelParsedResult ->
barcode.phone = parsed.toGms()
is SMSParsedResult ->
barcode.sms = parsed.toGms()
is WifiParsedResult ->
barcode.wifi = parsed.toGms()
is URIParsedResult ->
barcode.url = parsed.toGms()
is GeoParsedResult ->
barcode.geoPoint = parsed.toGms()
is CalendarParsedResult ->
barcode.calendarEvent = parsed.toGms()
is AddressBookParsedResult ->
barcode.contactInfo = parsed.toGms()
}
return barcode
}

View File

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'
android {
compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"
defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
apply from: '../gradle/publish-android.gradle'
description = 'microG implementation of play-services-vision'
dependencies {
api project(':play-services-base')
api project(':play-services-vision-api')
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<manifest package="org.microg.gms.vision"/>

View File

@ -9,6 +9,7 @@ include ':play-services-cast-framework-api'
include ':play-services-iid-api'
include ':play-services-location-api'
include ':play-services-nearby-api'
include ':play-services-vision-api'
include ':play-services-wearable-api'
include ':play-services-api'
@ -24,6 +25,7 @@ include ':play-services-maps-core-mapbox'
include ':play-services-maps-core-vtm'
include ':play-services-maps-core-vtm:vtm-microg-theme'
include ':play-services-nearby-core'
include ':play-services-vision-core'
include ':play-services-base-core-ui'
include ':play-services-nearby-core-ui'
@ -42,6 +44,7 @@ include ':play-services-gcm'
include ':play-services-iid'
include ':play-services-location'
include ':play-services-nearby'
include ':play-services-vision'
include ':play-services-wearable'
include ':play-services'