diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 00000000..4ed90b95 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,208 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, +AND DISTRIBUTION + + 1. Definitions. + + + +"License" shall mean the terms and conditions for use, reproduction, and distribution +as defined by Sections 1 through 9 of this document. + + + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + + + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct +or indirect, to cause the direction or management of such entity, whether +by contract or otherwise, or (ii) ownership of fifty percent (50%) or more +of the outstanding shares, or (iii) beneficial ownership of such entity. + + + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions +granted by this License. + + + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + + + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled object +code, generated documentation, and conversions to other media types. + + + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the Appendix +below). + + + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative +Works shall not include works that remain separable from, or merely link (or +bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative +Works thereof, that is intentionally submitted to Licensor for inclusion in +the Work by the copyright owner or by an individual or Legal Entity authorized +to submit on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication +sent to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + + + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently incorporated +within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable copyright license to reproduce, prepare +Derivative Works of, publicly display, publicly perform, sublicense, and distribute +the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, +each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, and otherwise +transfer the Work, where such license applies only to those patent claims +licensable by such Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work to which such +Contribution(s) was submitted. If You institute patent litigation against +any entity (including a cross-claim or counterclaim in a lawsuit) alleging +that the Work or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such litigation +is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + +(a) You must give any other recipients of the Work or Derivative Works a copy +of this License; and + +(b) You must cause any modified files to carry prominent notices stating that +You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source +form of the Work, excluding those notices that do not pertain to any part +of the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its distribution, +then any Derivative Works that You distribute must include a readable copy +of the attribution notices contained within such NOTICE file, excluding those +notices that do not pertain to any part of the Derivative Works, in at least +one of the following places: within a NOTICE text file distributed as part +of the Derivative Works; within the Source form or documentation, if provided +along with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works +that You distribute, alongside or as an addendum to the NOTICE text from the +Work, provided that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, +or distribution of Your modifications, or for any such Derivative Works as +a whole, provided Your use, reproduction, and distribution of the Work otherwise +complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to the +Licensor shall be under the terms and conditions of this License, without +any additional terms or conditions. Notwithstanding the above, nothing herein +shall supersede or modify the terms of any separate license agreement you +may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any warranties +or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR +A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness +of using or redistributing the Work and assume any risks associated with Your +exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or inability +to use the Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all other commercial +damages or losses), even if such Contributor has been advised of the possibility +of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work +or Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such obligations, +You may act only on Your own behalf and on Your sole responsibility, not on +behalf of any other Contributor, and only if You agree to indemnify, defend, +and hold each Contributor harmless for any liability incurred by, or claims +asserted against, such Contributor by reason of your accepting any such warranty +or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own identifying +information. (Don't include the brackets!) The text should be enclosed in +the appropriate comment syntax for the file format. We also recommend that +a file or class name and description of purpose be included on the same "printed +page" as the copyright notice for easier identification within third-party +archives. + +Copyright [yyyy] [name of copyright owner] + +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. diff --git a/LICENSES/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt new file mode 100644 index 00000000..3f92dfc5 --- /dev/null +++ b/LICENSES/CC-BY-4.0.txt @@ -0,0 +1,324 @@ +Creative Commons Attribution 4.0 International Creative Commons Corporation +("Creative Commons") is not a law firm and does not provide legal services +or legal advice. Distribution of Creative Commons public licenses does not +create a lawyer-client or other relationship. Creative Commons makes its licenses +and related information available on an "as-is" basis. Creative Commons gives +no warranties regarding its licenses, any material licensed under their terms +and conditions, or any related information. Creative Commons disclaims all +liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions +that creators and other rights holders may use to share original works of +authorship and other material subject to copyright and certain other rights +specified in the public license below. The following considerations are for +informational purposes only, are not exhaustive, and do not form part of our +licenses. + +Considerations for licensors: Our public licenses are intended for use by +those authorized to give the public permission to use material in ways otherwise +restricted by copyright and certain other rights. Our licenses are irrevocable. +Licensors should read and understand the terms and conditions of the license +they choose before applying it. Licensors should also secure all rights necessary +before applying our licenses so that the public can reuse the material as +expected. Licensors should clearly mark any material not subject to the license. +This includes other CC-licensed material, or material used under an exception +or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors + +Considerations for the public: By using one of our public licenses, a licensor +grants the public permission to use the licensed material under specified +terms and conditions. If the licensor's permission is not necessary for any +reason–for example, because of any applicable exception or limitation to copyright–then +that use is not regulated by the license. Our licenses grant only permissions +under copyright and certain other rights that a licensor has authority to +grant. Use of the licensed material may still be restricted for other reasons, +including because others have copyright or other rights in the material. A +licensor may make special requests, such as asking that all changes be marked +or described. Although not required by our licenses, you are encouraged to +respect those requests where reasonable. More considerations for the public +: wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution +4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to +be bound by the terms and conditions of this Creative Commons Attribution +4.0 International Public License ("Public License"). To the extent this Public +License may be interpreted as a contract, You are granted the Licensed Rights +in consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the Licensor +receives from making the Licensed Material available under these terms and +conditions. + +Section 1 – Definitions. + +a. Adapted Material means material subject to Copyright and Similar Rights +that is derived from or based upon the Licensed Material and in which the +Licensed Material is translated, altered, arranged, transformed, or otherwise +modified in a manner requiring permission under the Copyright and Similar +Rights held by the Licensor. For purposes of this Public License, where the +Licensed Material is a musical work, performance, or sound recording, Adapted +Material is always produced where the Licensed Material is synched in timed +relation with a moving image. + +b. Adapter's License means the license You apply to Your Copyright and Similar +Rights in Your contributions to Adapted Material in accordance with the terms +and conditions of this Public License. + +c. Copyright and Similar Rights means copyright and/or similar rights closely +related to copyright including, without limitation, performance, broadcast, +sound recording, and Sui Generis Database Rights, without regard to how the +rights are labeled or categorized. For purposes of this Public License, the +rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + +d. Effective Technological Measures means those measures that, in the absence +of proper authority, may not be circumvented under laws fulfilling obligations +under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, +and/or similar international agreements. + +e. Exceptions and Limitations means fair use, fair dealing, and/or any other +exception or limitation to Copyright and Similar Rights that applies to Your +use of the Licensed Material. + +f. Licensed Material means the artistic or literary work, database, or other +material to which the Licensor applied this Public License. + +g. Licensed Rights means the rights granted to You subject to the terms and +conditions of this Public License, which are limited to all Copyright and +Similar Rights that apply to Your use of the Licensed Material and that the +Licensor has authority to license. + +h. Licensor means the individual(s) or entity(ies) granting rights under this +Public License. + +i. Share means to provide material to the public by any means or process that +requires permission under the Licensed Rights, such as reproduction, public +display, public performance, distribution, dissemination, communication, or +importation, and to make material available to the public including in ways +that members of the public may access the material from a place and at a time +individually chosen by them. + +j. Sui Generis Database Rights means rights other than copyright resulting +from Directive 96/9/EC of the European Parliament and of the Council of 11 +March 1996 on the legal protection of databases, as amended and/or succeeded, +as well as other essentially equivalent rights anywhere in the world. + +k. You means the individual or entity exercising the Licensed Rights under +this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + +1. Subject to the terms and conditions of this Public License, the Licensor +hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, +irrevocable license to exercise the Licensed Rights in the Licensed Material +to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce, reproduce, and Share Adapted Material. + +2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions +and Limitations apply to Your use, this Public License does not apply, and +You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + +4. Media and formats; technical modifications allowed. The Licensor authorizes +You to exercise the Licensed Rights in all media and formats whether now known +or hereafter created, and to make technical modifications necessary to do +so. The Licensor waives and/or agrees not to assert any right or authority +to forbid You from making technical modifications necessary to exercise the +Licensed Rights, including technical modifications necessary to circumvent +Effective Technological Measures. For purposes of this Public License, simply +making modifications authorized by this Section 2(a)(4) never produces Adapted +Material. + + 5. Downstream recipients. + +A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed +Material automatically receives an offer from the Licensor to exercise the +Licensed Rights under the terms and conditions of this Public License. + +B. No downstream restrictions. You may not offer or impose any additional +or different terms or conditions on, or apply any Effective Technological +Measures to, the Licensed Material if doing so restricts exercise of the Licensed +Rights by any recipient of the Licensed Material. + +6. No endorsement. Nothing in this Public License constitutes or may be construed +as permission to assert or imply that You are, or that Your use of the Licensed +Material is, connected with, or sponsored, endorsed, or granted official status +by, the Licensor or others designated to receive attribution as provided in +Section 3(a)(1)(A)(i). + + b. Other rights. + +1. Moral rights, such as the right of integrity, are not licensed under this +Public License, nor are publicity, privacy, and/or other similar personality +rights; however, to the extent possible, the Licensor waives and/or agrees +not to assert any such rights held by the Licensor to the limited extent necessary +to allow You to exercise the Licensed Rights, but not otherwise. + +2. Patent and trademark rights are not licensed under this Public License. + +3. To the extent possible, the Licensor waives any right to collect royalties +from You for the exercise of the Licensed Rights, whether directly or through +a collecting society under any voluntary or waivable statutory or compulsory +licensing scheme. In all other cases the Licensor expressly reserves any right +to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following +conditions. + + a. Attribution. + +1. If You Share the Licensed Material (including in modified form), You must: + +A. retain the following if it is supplied by the Licensor with the Licensed +Material: + +i. identification of the creator(s) of the Licensed Material and any others +designated to receive attribution, in any reasonable manner requested by the +Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + +v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + +B. indicate if You modified the Licensed Material and retain an indication +of any previous modifications; and + +C. indicate the Licensed Material is licensed under this Public License, and +include the text of, or the URI or hyperlink to, this Public License. + +2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner +based on the medium, means, and context in which You Share the Licensed Material. +For example, it may be reasonable to satisfy the conditions by providing a +URI or hyperlink to a resource that includes the required information. + +3. If requested by the Licensor, You must remove any of the information required +by Section 3(a)(1)(A) to the extent reasonably practicable. + +4. If You Share Adapted Material You produce, the Adapter's License You apply +must not prevent recipients of the Adapted Material from complying with this +Public License. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to +Your use of the Licensed Material: + +a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, +reuse, reproduce, and Share all or a substantial portion of the contents of +the database; + +b. if You include all or a substantial portion of the database contents in +a database in which You have Sui Generis Database Rights, then the database +in which You have Sui Generis Database Rights (but not its individual contents) +is Adapted Material; and + +c. You must comply with the conditions in Section 3(a) if You Share all or +a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not replace +Your obligations under this Public License where the Licensed Rights include +other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + +a. Unless otherwise separately undertaken by the Licensor, to the extent possible, +the Licensor offers the Licensed Material as-is and as-available, and makes +no representations or warranties of any kind concerning the Licensed Material, +whether express, implied, statutory, or other. This includes, without limitation, +warranties of title, merchantability, fitness for a particular purpose, non-infringement, +absence of latent or other defects, accuracy, or the presence or absence of +errors, whether or not known or discoverable. Where disclaimers of warranties +are not allowed in full or in part, this disclaimer may not apply to You. + +b. To the extent possible, in no event will the Licensor be liable to You +on any legal theory (including, without limitation, negligence) or otherwise +for any direct, special, indirect, incidental, consequential, punitive, exemplary, +or other losses, costs, expenses, or damages arising out of this Public License +or use of the Licensed Material, even if the Licensor has been advised of +the possibility of such losses, costs, expenses, or damages. Where a limitation +of liability is not allowed in full or in part, this limitation may not apply +to You. + +c. The disclaimer of warranties and limitation of liability provided above +shall be interpreted in a manner that, to the extent possible, most closely +approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + +a. This Public License applies for the term of the Copyright and Similar Rights +licensed here. However, if You fail to comply with this Public License, then +Your rights under this Public License terminate automatically. + +b. Where Your right to use the Licensed Material has terminated under Section +6(a), it reinstates: + +1. automatically as of the date the violation is cured, provided it is cured +within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + +c. For the avoidance of doubt, this Section 6(b) does not affect any right +the Licensor may have to seek remedies for Your violations of this Public +License. + +d. For the avoidance of doubt, the Licensor may also offer the Licensed Material +under separate terms or conditions or stop distributing the Licensed Material +at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + +a. The Licensor shall not be bound by any additional or different terms or +conditions communicated by You unless expressly agreed. + +b. Any arrangements, understandings, or agreements regarding the Licensed +Material not stated herein are separate from and independent of the terms +and conditions of this Public License. + +Section 8 – Interpretation. + +a. For the avoidance of doubt, this Public License does not, and shall not +be interpreted to, reduce, limit, restrict, or impose conditions on any use +of the Licensed Material that could lawfully be made without permission under +this Public License. + +b. To the extent possible, if any provision of this Public License is deemed +unenforceable, it shall be automatically reformed to the minimum extent necessary +to make it enforceable. If the provision cannot be reformed, it shall be severed +from this Public License without affecting the enforceability of the remaining +terms and conditions. + +c. No term or condition of this Public License will be waived and no failure +to comply consented to unless expressly agreed to by the Licensor. + +d. Nothing in this Public License constitutes or may be interpreted as a limitation +upon, or waiver of, any privileges and immunities that apply to the Licensor +or You, including from the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, Creative +Commons may elect to apply one of its public licenses to material it publishes +and in those instances will be considered the "Licensor." The text of the +Creative Commons public licenses is dedicated to the public domain under the +CC0 Public Domain Dedication. Except for the limited purpose of indicating +that material is shared under a Creative Commons public license or as otherwise +permitted by the Creative Commons policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark "Creative Commons" +or any other trademark or logo of Creative Commons without its prior written +consent including, without limitation, in connection with any unauthorized +modifications to any of its public licenses or any other arrangements, understandings, +or agreements concerning use of licensed material. For the avoidance of doubt, +this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/firebase-dynamic-links-api/build.gradle b/firebase-dynamic-links-api/build.gradle new file mode 100644 index 00000000..32edbc9b --- /dev/null +++ b/firebase-dynamic-links-api/build.gradle @@ -0,0 +1,49 @@ +/* + * Copyright 2019 e Foundation + * + * 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. + */ + +apply plugin: 'com.android.library' + +String getMyVersionName() { + def stdout = new ByteArrayOutputStream() + if (rootProject.file("gradlew").exists()) + exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout } + else // automatic build system, don't tag dirty + exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout } + return stdout.toString().trim().substring(1) +} + +group = 'org.microg' +version = getMyVersionName() + +android { + compileSdkVersion androidCompileSdk() + buildToolsVersion "$androidBuildVersionTools" + + defaultConfig { + versionName getMyVersionName() + minSdkVersion androidMinSdk() + targetSdkVersion androidTargetSdk() + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + api project(':play-services-basement') +} diff --git a/firebase-dynamic-links-api/gradle.properties b/firebase-dynamic-links-api/gradle.properties new file mode 100644 index 00000000..c601b6d6 --- /dev/null +++ b/firebase-dynamic-links-api/gradle.properties @@ -0,0 +1,34 @@ +# +# Copyright 2019 e Foundation +# +# 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. +# + +POM_NAME=Firebase Dynamic Links API +POM_DESCRIPTION=Interfaces and objects for IPC between Firebase Library and microG + +POM_PACKAGING=aar + +POM_URL=https://github.com/microg/android_external_GmsApi + +POM_SCM_URL=https://github.com/microg/android_external_GmsApi +POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsApi.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsApi.git + +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo + +POM_DEVELOPER_ID=alexandruchircu +POM_DEVELOPER_NAME=Alexandru Chircu + diff --git a/play-services-core/src/main/res/xml/preferences_checkin.xml b/firebase-dynamic-links-api/src/main/AndroidManifest.xml similarity index 70% rename from play-services-core/src/main/res/xml/preferences_checkin.xml rename to firebase-dynamic-links-api/src/main/AndroidManifest.xml index 45c982a7..ae17555c 100644 --- a/play-services-core/src/main/res/xml/preferences_checkin.xml +++ b/firebase-dynamic-links-api/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - - - \ No newline at end of file + diff --git a/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/DynamicLinkData.aidl b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/DynamicLinkData.aidl new file mode 100644 index 00000000..5862178a --- /dev/null +++ b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/DynamicLinkData.aidl @@ -0,0 +1,3 @@ +package com.google.firebase.dynamiclinks.internal; + +parcelable DynamicLinkData; \ No newline at end of file diff --git a/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksCallbacks.aidl b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksCallbacks.aidl new file mode 100644 index 00000000..9f9915ff --- /dev/null +++ b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksCallbacks.aidl @@ -0,0 +1,12 @@ +package com.google.firebase.dynamiclinks.internal; + + +import com.google.firebase.dynamiclinks.internal.DynamicLinkData; +import com.google.firebase.dynamiclinks.internal.ShortDynamicLink; + +import com.google.android.gms.common.api.Status; + +interface IDynamicLinksCallbacks { + void onStatusDynamicLinkData(in Status status, in DynamicLinkData dldata) = 0; + void onStatusShortDynamicLink(in Status status, in ShortDynamicLink sdlink) = 1; +} diff --git a/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksService.aidl b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksService.aidl new file mode 100644 index 00000000..57f083f5 --- /dev/null +++ b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/IDynamicLinksService.aidl @@ -0,0 +1,12 @@ +package com.google.firebase.dynamiclinks.internal; + + +import com.google.firebase.dynamiclinks.internal.IDynamicLinksCallbacks; + +import android.os.Bundle; + + +interface IDynamicLinksService { + void getInitialLink(IDynamicLinksCallbacks callback, String var2) = 0; + void func2(IDynamicLinksCallbacks callback, in Bundle var2) = 1; +} diff --git a/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.aidl b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.aidl new file mode 100644 index 00000000..f4852a03 --- /dev/null +++ b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.aidl @@ -0,0 +1,3 @@ +package com.google.firebase.dynamiclinks.internal; + +parcelable ShortDynamicLink; \ No newline at end of file diff --git a/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/Warning.aidl b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/Warning.aidl new file mode 100644 index 00000000..4331c92a --- /dev/null +++ b/firebase-dynamic-links-api/src/main/aidl/com/google/firebase/dynamiclinks/internal/Warning.aidl @@ -0,0 +1,3 @@ +package com.google.firebase.dynamiclinks.internal; + +parcelable Warning; \ No newline at end of file diff --git a/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java new file mode 100644 index 00000000..02270cd1 --- /dev/null +++ b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/DynamicLinkData.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 e Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.firebase.dynamiclinks.internal; + + +import org.microg.safeparcel.AutoSafeParcelable; +import org.microg.safeparcel.SafeParceled; + +import android.os.Bundle; +import android.net.Uri; + + +public class DynamicLinkData extends AutoSafeParcelable { + @SafeParceled(1) + public final String dynamicLink; + + @SafeParceled(2) + public final String deepLink; + + @SafeParceled(3) + public final int minVersion; + + @SafeParceled(4) + public final long clickTimestamp; + + @SafeParceled(5) + public final Bundle extensionBundle; + + @SafeParceled(6) + public final Uri redirectUrl; + + public DynamicLinkData() { + dynamicLink = new String(); + deepLink = new String(); + minVersion = 0; + clickTimestamp = 0; + extensionBundle = new Bundle(); + redirectUrl = Uri.EMPTY; + } + + + public static final Creator CREATOR = new AutoCreator(DynamicLinkData.class); +} \ No newline at end of file diff --git a/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.java b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.java new file mode 100644 index 00000000..893e4098 --- /dev/null +++ b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/ShortDynamicLink.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 e Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.firebase.dynamiclinks.internal; + + +import com.google.firebase.dynamiclinks.internal.Warning; + +import org.microg.safeparcel.AutoSafeParcelable; +import org.microg.safeparcel.SafeParceled; + +import android.net.Uri; +import java.util.List; +import java.util.ArrayList; + + +public class ShortDynamicLink extends AutoSafeParcelable { + @SafeParceled(1) + public final Uri shortLink; + + @SafeParceled(2) + public final Uri previewLink; + + @SafeParceled(3) + public final List warnings; + + + public ShortDynamicLink() { + shortLink = Uri.EMPTY; + previewLink = Uri.EMPTY; + + warnings = new ArrayList<>(); + } + + + public static final Creator CREATOR = new AutoCreator(ShortDynamicLink.class); +} \ No newline at end of file diff --git a/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/Warning.java b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/Warning.java new file mode 100644 index 00000000..950f3de7 --- /dev/null +++ b/firebase-dynamic-links-api/src/main/java/com/google/firebase/dynamiclinks/internal/Warning.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 e Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.firebase.dynamiclinks.internal; + + +import org.microg.safeparcel.AutoSafeParcelable; +import org.microg.safeparcel.SafeParceled; + + +public class Warning extends AutoSafeParcelable { + @SafeParceled(1) + private int versionCode = 1; + + @SafeParceled(2) + public final String message; + + + public Warning() { + message = null; + } + + + public static final Creator CREATOR = new AutoCreator(Warning.class); +} \ No newline at end of file diff --git a/play-services-api/build.gradle b/play-services-api/build.gradle index 5e627850..d3064fa5 100644 --- a/play-services-api/build.gradle +++ b/play-services-api/build.gradle @@ -34,6 +34,7 @@ android { dependencies { api project(':play-services-basement') + api project(':play-services-appinvite-api') api project(':play-services-cast-api') api project(':play-services-cast-framework-api') api project(':play-services-iid-api') diff --git a/play-services-basement/src/main/aidl/com/google/android/gms/common/internal/ISignInButtonCreator.aidl b/play-services-api/src/main/aidl/com/google/android/gms/common/internal/ISignInButtonCreator.aidl similarity index 100% rename from play-services-basement/src/main/aidl/com/google/android/gms/common/internal/ISignInButtonCreator.aidl rename to play-services-api/src/main/aidl/com/google/android/gms/common/internal/ISignInButtonCreator.aidl diff --git a/play-services-basement/src/main/aidl/com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl b/play-services-api/src/main/aidl/com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl similarity index 100% rename from play-services-basement/src/main/aidl/com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl rename to play-services-api/src/main/aidl/com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl diff --git a/play-services-basement/src/main/java/com/google/android/gms/common/server/FavaDiagnosticsEntity.java b/play-services-api/src/main/java/com/google/android/gms/common/server/FavaDiagnosticsEntity.java similarity index 100% rename from play-services-basement/src/main/java/com/google/android/gms/common/server/FavaDiagnosticsEntity.java rename to play-services-api/src/main/java/com/google/android/gms/common/server/FavaDiagnosticsEntity.java diff --git a/play-services-appinvite-api/build.gradle b/play-services-appinvite-api/build.gradle new file mode 100644 index 00000000..32edbc9b --- /dev/null +++ b/play-services-appinvite-api/build.gradle @@ -0,0 +1,49 @@ +/* + * Copyright 2019 e Foundation + * + * 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. + */ + +apply plugin: 'com.android.library' + +String getMyVersionName() { + def stdout = new ByteArrayOutputStream() + if (rootProject.file("gradlew").exists()) + exec { commandLine 'git', 'describe', '--tags', '--always', '--dirty'; standardOutput = stdout } + else // automatic build system, don't tag dirty + exec { commandLine 'git', 'describe', '--tags', '--always'; standardOutput = stdout } + return stdout.toString().trim().substring(1) +} + +group = 'org.microg' +version = getMyVersionName() + +android { + compileSdkVersion androidCompileSdk() + buildToolsVersion "$androidBuildVersionTools" + + defaultConfig { + versionName getMyVersionName() + minSdkVersion androidMinSdk() + targetSdkVersion androidTargetSdk() + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + api project(':play-services-basement') +} diff --git a/play-services-appinvite-api/gradle.properties b/play-services-appinvite-api/gradle.properties new file mode 100644 index 00000000..7215aee4 --- /dev/null +++ b/play-services-appinvite-api/gradle.properties @@ -0,0 +1,34 @@ +# +# Copyright 2019 e Foundation +# +# 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. +# + +POM_NAME=Play Services Internal AppInvite API +POM_DESCRIPTION=Interfaces and objects for IPC between Play Services Library and Play Services Core + +POM_PACKAGING=aar + +POM_URL=https://github.com/microg/android_external_GmsApi + +POM_SCM_URL=https://github.com/microg/android_external_GmsApi +POM_SCM_CONNECTION=scm:git@github.com:microg/android_external_GmsApi.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:microg/android_external_GmsApi.git + +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo + +POM_DEVELOPER_ID=alexandruchircu +POM_DEVELOPER_NAME=Alexandru Chircu + diff --git a/play-services-appinvite-api/src/main/AndroidManifest.xml b/play-services-appinvite-api/src/main/AndroidManifest.xml new file mode 100644 index 00000000..da7741f9 --- /dev/null +++ b/play-services-appinvite-api/src/main/AndroidManifest.xml @@ -0,0 +1,18 @@ + + + + diff --git a/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteCallbacks.aidl b/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteCallbacks.aidl new file mode 100644 index 00000000..66c64d7e --- /dev/null +++ b/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteCallbacks.aidl @@ -0,0 +1,11 @@ +package com.google.android.gms.appinvite.internal; + + +import com.google.android.gms.common.api.Status; +import android.content.Intent; + + +interface IAppInviteCallbacks { + void onStatus(in Status status) = 0; + void onStatusIntent(in Status status, in Intent intent) = 1; +} diff --git a/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteService.aidl b/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteService.aidl new file mode 100644 index 00000000..630edd43 --- /dev/null +++ b/play-services-appinvite-api/src/main/aidl/com/google/android/gms/appinvite/internal/IAppInviteService.aidl @@ -0,0 +1,14 @@ +package com.google.android.gms.appinvite.internal; + + +import com.google.android.gms.appinvite.internal.IAppInviteCallbacks; + +import com.google.android.gms.dynamic.IObjectWrapper; +import com.google.android.gms.common.api.Status; + + +interface IAppInviteService { + void updateInvitationOnInstall(IAppInviteCallbacks callback, String invitationId) = 0; + void convertInvitation(IAppInviteCallbacks callback, String invitationId) = 1; + void getInvitation(IAppInviteCallbacks callback) = 2; +} diff --git a/play-services-base-api/build.gradle b/play-services-base-api/build.gradle new file mode 100644 index 00000000..70d9d624 --- /dev/null +++ b/play-services-base-api/build.gradle @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2015 microG Project Team + * + * 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. + */ + +apply plugin: 'com.android.library' + +dependencies { + api project(':play-services-basement') +} + +android { + compileSdkVersion androidCompileSdk + buildToolsVersion "$androidBuildVersionTools" + + aidlPackageWhiteList "com/google/android/gms/common/data/DataHolder.aidl" + aidlPackageWhiteList "com/google/android/gms/common/images/WebImage.aidl" + + defaultConfig { + versionName version + minSdkVersion androidMinSdk + targetSdkVersion androidTargetSdk + } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } +} diff --git a/play-services-base-api/src/main/AndroidManifest.xml b/play-services-base-api/src/main/AndroidManifest.xml new file mode 100644 index 00000000..7c8eeef3 --- /dev/null +++ b/play-services-base-api/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + diff --git a/play-services-base-api/src/main/aidl/com/google/android/gms/common/api/internal/IStatusCallback.aidl b/play-services-base-api/src/main/aidl/com/google/android/gms/common/api/internal/IStatusCallback.aidl new file mode 100644 index 00000000..6355a13b --- /dev/null +++ b/play-services-base-api/src/main/aidl/com/google/android/gms/common/api/internal/IStatusCallback.aidl @@ -0,0 +1,7 @@ +package com.google.android.gms.common.api.internal; + +import com.google.android.gms.common.api.Status; + +interface IStatusCallback { + void onResult(in Status status); +} diff --git a/play-services-basement/src/main/aidl/com/google/android/gms/common/data/DataHolder.aidl b/play-services-base-api/src/main/aidl/com/google/android/gms/common/data/DataHolder.aidl similarity index 100% rename from play-services-basement/src/main/aidl/com/google/android/gms/common/data/DataHolder.aidl rename to play-services-base-api/src/main/aidl/com/google/android/gms/common/data/DataHolder.aidl diff --git a/play-services-basement/src/main/aidl/com/google/android/gms/common/images/WebImage.aidl b/play-services-base-api/src/main/aidl/com/google/android/gms/common/images/WebImage.aidl similarity index 100% rename from play-services-basement/src/main/aidl/com/google/android/gms/common/images/WebImage.aidl rename to play-services-base-api/src/main/aidl/com/google/android/gms/common/images/WebImage.aidl diff --git a/play-services-base-api/src/main/java/com/google/android/gms/auth/api/signin/GoogleSignInAccount.java b/play-services-base-api/src/main/java/com/google/android/gms/auth/api/signin/GoogleSignInAccount.java new file mode 100644 index 00000000..802db9a3 --- /dev/null +++ b/play-services-base-api/src/main/java/com/google/android/gms/auth/api/signin/GoogleSignInAccount.java @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.auth.api.signin; + +import org.microg.safeparcel.AutoSafeParcelable; + +public class GoogleSignInAccount extends AutoSafeParcelable { + public static final Creator CREATOR = new AutoCreator(GoogleSignInAccount.class); +} diff --git a/play-services-basement/src/main/java/com/google/android/gms/common/data/DataHolder.java b/play-services-base-api/src/main/java/com/google/android/gms/common/data/DataHolder.java similarity index 100% rename from play-services-basement/src/main/java/com/google/android/gms/common/data/DataHolder.java rename to play-services-base-api/src/main/java/com/google/android/gms/common/data/DataHolder.java diff --git a/play-services-basement/src/main/java/com/google/android/gms/common/data/Freezable.java b/play-services-base-api/src/main/java/com/google/android/gms/common/data/Freezable.java similarity index 100% rename from play-services-basement/src/main/java/com/google/android/gms/common/data/Freezable.java rename to play-services-base-api/src/main/java/com/google/android/gms/common/data/Freezable.java diff --git a/play-services-basement/src/main/java/com/google/android/gms/common/images/WebImage.java b/play-services-base-api/src/main/java/com/google/android/gms/common/images/WebImage.java similarity index 100% rename from play-services-basement/src/main/java/com/google/android/gms/common/images/WebImage.java rename to play-services-base-api/src/main/java/com/google/android/gms/common/images/WebImage.java diff --git a/play-services-base/build.gradle b/play-services-base/build.gradle index 27a432be..f26a4e11 100644 --- a/play-services-base/build.gradle +++ b/play-services-base/build.gradle @@ -35,6 +35,7 @@ android { dependencies { api project(':play-services-basement') api project(':play-services-tasks') + api project(':play-services-base-api') implementation "androidx.fragment:fragment:$fragmentVersion" implementation "com.google.android.gms:play-services-base:17.3.0" diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/AccountInfo.java b/play-services-base/src/main/java/com/google/android/gms/common/api/AccountInfo.java index 94c11015..30d6a169 100644 --- a/play-services-base/src/main/java/com/google/android/gms/common/api/AccountInfo.java +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/AccountInfo.java @@ -18,6 +18,7 @@ package com.google.android.gms.common.api; import org.microg.safeparcel.AutoSafeParcelable; +@Deprecated public class AccountInfo extends AutoSafeParcelable { public static final Creator CREATOR = new AutoCreator(AccountInfo.class); } diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/Api.java b/play-services-base/src/main/java/com/google/android/gms/common/api/Api.java index 610da966..065fff8a 100644 --- a/play-services-base/src/main/java/com/google/android/gms/common/api/Api.java +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/Api.java @@ -16,8 +16,12 @@ package com.google.android.gms.common.api; +import android.accounts.Account; + +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; + import org.microg.gms.common.PublicApi; -import org.microg.gms.common.api.ApiBuilder; +import org.microg.gms.common.api.ApiClientBuilder; /** * Describes a section of the Google Play Services API that should be made available. Instances of @@ -33,16 +37,15 @@ import org.microg.gms.common.api.ApiBuilder; */ @PublicApi public final class Api { - - private final ApiBuilder builder; + private final ApiClientBuilder builder; @PublicApi(exclude = true) - public Api(ApiBuilder builder) { + public Api(ApiClientBuilder builder) { this.builder = builder; } @PublicApi(exclude = true) - public ApiBuilder getBuilder() { + public ApiClientBuilder getBuilder() { return builder; } @@ -79,6 +82,22 @@ public final class Api { @PublicApi interface Optional extends HasOptions, NotRequiredOptions { } + + /** + * An interface for {@link ApiOptions} that include an account. + */ + @PublicApi + interface HasAccountOptions extends HasOptions, NotRequiredOptions { + Account getAccount(); + } + + /** + * An interface for {@link ApiOptions} that includes a {@link GoogleSignInAccount} + */ + @PublicApi + interface HasGoogleSignInAccountOptions extends HasOptions { + GoogleSignInAccount getGoogleSignInAccount(); + } } } diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApi.java b/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApi.java new file mode 100644 index 00000000..455ba014 --- /dev/null +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApi.java @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.common.api; + +import android.content.Context; + +import com.google.android.gms.common.api.internal.ApiKey; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; + +import org.microg.gms.common.PublicApi; +import org.microg.gms.common.api.ApiClient; +import org.microg.gms.common.api.GoogleApiManager; +import org.microg.gms.common.api.PendingGoogleApiCall; + +@PublicApi +public abstract class GoogleApi implements HasApiKey { + private GoogleApiManager manager; + @PublicApi(exclude = true) + public Api api; + + @PublicApi(exclude = true) + protected GoogleApi(Context context, Api api) { + this.api = api; + this.manager = GoogleApiManager.getInstance(context); + } + + @PublicApi(exclude = true) + protected Task scheduleTask(PendingGoogleApiCall apiCall) { + TaskCompletionSource completionSource = new TaskCompletionSource<>(); + manager.scheduleTask(this, apiCall, completionSource); + return completionSource.getTask(); + } + + @Override + @PublicApi(exclude = true) + public ApiKey getApiKey() { + return null; + } + + @PublicApi(exclude = true) + public O getOptions() { + return null; + } +} diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApiClient.java b/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApiClient.java index 1cd0525f..fb7088e6 100644 --- a/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApiClient.java +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/GoogleApiClient.java @@ -29,6 +29,7 @@ import com.google.android.gms.common.ConnectionResult; import org.microg.gms.auth.AuthConstants; import org.microg.gms.common.PublicApi; +import org.microg.gms.common.api.ApiClientSettings; import org.microg.gms.common.api.GoogleApiClientImpl; import java.util.HashMap; @@ -56,6 +57,7 @@ import java.util.concurrent.TimeUnit; * in {@link Activity#onStop()}, regardless of the state. */ @PublicApi +@Deprecated public interface GoogleApiClient { /** * Connects the client to Google Play services. Blocks until the connection either succeeds or @@ -271,7 +273,7 @@ public interface GoogleApiClient { * attempt fails. */ public Builder(Context context, ConnectionCallbacks connectedListener, - OnConnectionFailedListener connectionFailedListener) { + OnConnectionFailedListener connectionFailedListener) { this(context); addConnectionCallbacks(connectedListener); addOnConnectionFailedListener(connectionFailedListener); @@ -358,16 +360,15 @@ public interface GoogleApiClient { * @return The {@link GoogleApiClient} object. */ public GoogleApiClient build() { - return new GoogleApiClientImpl(context, looper, getAccountInfo(), apis, - connectionCallbacks, connectionFailedListeners, clientId); + return new GoogleApiClientImpl(context, looper, getClientSettings(), apis, connectionCallbacks, connectionFailedListeners, clientId); } - private AccountInfo getAccountInfo() { + private ApiClientSettings getClientSettings() { return null; } public Builder enableAutoManage(FragmentActivity fragmentActivity, int cliendId, - OnConnectionFailedListener unresolvedConnectionFailedListener) + OnConnectionFailedListener unresolvedConnectionFailedListener) throws NullPointerException, IllegalArgumentException, IllegalStateException { this.fragmentActivity = fragmentActivity; this.clientId = cliendId; @@ -433,7 +434,8 @@ public interface GoogleApiClient { * service. Most applications implement {@link #onConnected(Bundle)} to start making requests. */ @PublicApi - interface ConnectionCallbacks { + @Deprecated + interface ConnectionCallbacks extends org.microg.gms.common.api.ConnectionCallbacks { /** * A suspension cause informing that the service has been killed. */ @@ -442,34 +444,6 @@ public interface GoogleApiClient { * A suspension cause informing you that a peer device connection was lost. */ int CAUSE_NETWORK_LOST = 2; - - /** - * After calling {@link #connect()}, this method will be invoked asynchronously when the - * connect request has successfully completed. After this callback, the application can - * make requests on other methods provided by the client and expect that no user - * intervention is required to call methods that use account and scopes provided to the - * client constructor. - *

- * Note that the contents of the {@code connectionHint} Bundle are defined by the specific - * services. Please see the documentation of the specific implementation of - * {@link GoogleApiClient} you are using for more information. - * - * @param connectionHint Bundle of data provided to clients by Google Play services. May - * be null if no content is provided by the service. - */ - void onConnected(Bundle connectionHint); - - /** - * Called when the client is temporarily in a disconnected state. This can happen if there - * is a problem with the remote service (e.g. a crash or resource problem causes it to be - * killed by the system). When called, all requests have been canceled and no outstanding - * listeners will be executed. GoogleApiClient will automatically attempt to restore the - * connection. Applications should disable UI components that require the service, and wait - * for a call to {@link #onConnected(Bundle)} to re-enable them. - * - * @param cause The reason for the disconnection. Defined by constants {@code CAUSE_*}. - */ - void onConnectionSuspended(int cause); } /** @@ -478,18 +452,7 @@ public interface GoogleApiClient { * resolution. */ @PublicApi - interface OnConnectionFailedListener { - /** - * Called when there was an error connecting the client to the service. - * - * @param result A {@link ConnectionResult} that can be used for resolving the error, and - * deciding what sort of error occurred. To resolve the error, the resolution - * must be started from an activity with a non-negative {@code requestCode} - * passed to {@link ConnectionResult#startResolutionForResult(Activity, int)}. - * Applications should implement {@link Activity#onActivityResult} in their - * Activity to call {@link #connect()} again if the user has resolved the - * issue (resultCode is {@link Activity#RESULT_OK}). - */ - void onConnectionFailed(ConnectionResult result); + @Deprecated + interface OnConnectionFailedListener extends org.microg.gms.common.api.OnConnectionFailedListener { } } diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/HasApiKey.java b/play-services-base/src/main/java/com/google/android/gms/common/api/HasApiKey.java new file mode 100644 index 00000000..e208b4d8 --- /dev/null +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/HasApiKey.java @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.common.api; + +import com.google.android.gms.common.api.internal.ApiKey; + +public interface HasApiKey { + ApiKey getApiKey(); +} diff --git a/play-services-base/src/main/java/com/google/android/gms/common/api/internal/ApiKey.java b/play-services-base/src/main/java/com/google/android/gms/common/api/internal/ApiKey.java new file mode 100644 index 00000000..5a42d8fd --- /dev/null +++ b/play-services-base/src/main/java/com/google/android/gms/common/api/internal/ApiKey.java @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.common.api.internal; + +import com.google.android.gms.common.api.Api; + +public class ApiKey { + private Api api; +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/DummyApiConnection.java b/play-services-base/src/main/java/org/microg/gms/common/DummyApiClient.java similarity index 90% rename from play-services-base/src/main/java/org/microg/gms/common/DummyApiConnection.java rename to play-services-base/src/main/java/org/microg/gms/common/DummyApiClient.java index 9476d3e7..132a6148 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/DummyApiConnection.java +++ b/play-services-base/src/main/java/org/microg/gms/common/DummyApiClient.java @@ -16,9 +16,9 @@ package org.microg.gms.common; -import org.microg.gms.common.api.ApiConnection; +import org.microg.gms.common.api.ApiClient; -public class DummyApiConnection implements ApiConnection { +public class DummyApiClient implements ApiClient { private boolean connected = false; @Override diff --git a/play-services-base/src/main/java/org/microg/gms/common/GmsClient.java b/play-services-base/src/main/java/org/microg/gms/common/GmsClient.java index 779f4769..64ac6942 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/GmsClient.java +++ b/play-services-base/src/main/java/org/microg/gms/common/GmsClient.java @@ -27,19 +27,20 @@ import android.os.RemoteException; import android.util.Log; import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.internal.GetServiceRequest; import com.google.android.gms.common.internal.IGmsCallbacks; import com.google.android.gms.common.internal.IGmsServiceBroker; -import org.microg.gms.common.api.ApiConnection; +import org.microg.gms.common.api.ApiClient; +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; -public abstract class GmsClient implements ApiConnection { +public abstract class GmsClient implements ApiClient { private static final String TAG = "GmsClient"; private final Context context; - protected final GoogleApiClient.ConnectionCallbacks callbacks; - protected final GoogleApiClient.OnConnectionFailedListener connectionFailedListener; + protected final ConnectionCallbacks callbacks; + protected final OnConnectionFailedListener connectionFailedListener; protected ConnectionState state = ConnectionState.NOT_CONNECTED; private ServiceConnection serviceConnection; private I serviceInterface; @@ -49,8 +50,7 @@ public abstract class GmsClient implements ApiConnection { protected Account account = null; protected Bundle extras = new Bundle(); - public GmsClient(Context context, GoogleApiClient.ConnectionCallbacks callbacks, - GoogleApiClient.OnConnectionFailedListener connectionFailedListener, String actionString) { + public GmsClient(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener, String actionString) { this.context = context; this.callbacks = callbacks; this.connectionFailedListener = connectionFailedListener; @@ -89,8 +89,7 @@ public abstract class GmsClient implements ApiConnection { } public void handleConnectionFailed() { - connectionFailedListener.onConnectionFailed(new ConnectionResult(ConnectionResult - .API_UNAVAILABLE, null)); + connectionFailedListener.onConnectionFailed(new ConnectionResult(ConnectionResult.API_UNAVAILABLE, null)); } @Override @@ -147,8 +146,7 @@ public abstract class GmsClient implements ApiConnection { public void onServiceConnected(ComponentName componentName, IBinder iBinder) { try { Log.d(TAG, "ServiceConnection : onServiceConnected(" + componentName + ")"); - onConnectedToBroker(IGmsServiceBroker.Stub.asInterface(iBinder), - new GmsCallbacks()); + onConnectedToBroker(IGmsServiceBroker.Stub.asInterface(iBinder), new GmsCallbacks()); } catch (RemoteException e) { disconnect(); } diff --git a/play-services-base/src/main/java/org/microg/gms/common/GmsConnector.java b/play-services-base/src/main/java/org/microg/gms/common/GmsConnector.java index 9de363f6..8013d70f 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/GmsConnector.java +++ b/play-services-base/src/main/java/org/microg/gms/common/GmsConnector.java @@ -27,10 +27,10 @@ import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.Result; import org.microg.gms.common.api.AbstractPendingResult; -import org.microg.gms.common.api.ApiConnection; +import org.microg.gms.common.api.ApiClient; import org.microg.gms.common.api.GoogleApiClientImpl; -public class GmsConnector { +public class GmsConnector { private static final String TAG = "GmsConnector"; private final GoogleApiClientImpl apiClient; @@ -43,7 +43,7 @@ public class GmsConnector { this.callback = callback; } - public static PendingResult call(GoogleApiClient client, Api api, GmsConnector.Callback callback) { + public static PendingResult call(GoogleApiClient client, Api api, GmsConnector.Callback callback) { return new GmsConnector(client, api, callback).connect(); } diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClient.java similarity index 95% rename from play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java rename to play-services-base/src/main/java/org/microg/gms/common/api/ApiClient.java index 9ca239b4..602e150e 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/api/ApiConnection.java +++ b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClient.java @@ -16,7 +16,7 @@ package org.microg.gms.common.api; -public interface ApiConnection { +public interface ApiClient { void connect(); void disconnect(); diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/ApiBuilder.java b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClientBuilder.java similarity index 64% rename from play-services-base/src/main/java/org/microg/gms/common/api/ApiBuilder.java rename to play-services-base/src/main/java/org/microg/gms/common/api/ApiClientBuilder.java index 7d1fb020..b5aa386f 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/api/ApiBuilder.java +++ b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClientBuilder.java @@ -19,12 +19,8 @@ package org.microg.gms.common.api; import android.content.Context; import android.os.Looper; -import com.google.android.gms.common.api.AccountInfo; import com.google.android.gms.common.api.Api; -import com.google.android.gms.common.api.GoogleApiClient; -public interface ApiBuilder { - ApiConnection build(Context context, Looper looper, O options, AccountInfo accountInfo, - GoogleApiClient.ConnectionCallbacks callbacks, - GoogleApiClient.OnConnectionFailedListener connectionFailedListener); +public interface ApiClientBuilder { + ApiClient build(O options, Context context, Looper looper, ApiClientSettings clientSettings, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener); } diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/ApiClientSettings.java b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClientSettings.java new file mode 100644 index 00000000..d1e314a7 --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/ApiClientSettings.java @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +public class ApiClientSettings { +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/ConnectionCallbacks.java b/play-services-base/src/main/java/org/microg/gms/common/api/ConnectionCallbacks.java new file mode 100644 index 00000000..738a43d3 --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/ConnectionCallbacks.java @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +import android.os.Bundle; + +import com.google.android.gms.common.api.GoogleApiClient; + +public interface ConnectionCallbacks { + + /** + * After calling {@link #connect()}, this method will be invoked asynchronously when the + * connect request has successfully completed. After this callback, the application can + * make requests on other methods provided by the client and expect that no user + * intervention is required to call methods that use account and scopes provided to the + * client constructor. + *

+ * Note that the contents of the {@code connectionHint} Bundle are defined by the specific + * services. Please see the documentation of the specific implementation of + * {@link GoogleApiClient} you are using for more information. + * + * @param connectionHint Bundle of data provided to clients by Google Play services. May + * be null if no content is provided by the service. + */ + void onConnected(Bundle connectionHint); + + /** + * Called when the client is temporarily in a disconnected state. This can happen if there + * is a problem with the remote service (e.g. a crash or resource problem causes it to be + * killed by the system). When called, all requests have been canceled and no outstanding + * listeners will be executed. GoogleApiClient will automatically attempt to restore the + * connection. Applications should disable UI components that require the service, and wait + * for a call to {@link #onConnected(Bundle)} to re-enable them. + * + * @param cause The reason for the disconnection. Defined by constants {@code CAUSE_*}. + */ + void onConnectionSuspended(int cause); +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiClientImpl.java b/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiClientImpl.java index 8c802d4a..11233697 100644 --- a/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiClientImpl.java +++ b/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiClientImpl.java @@ -20,11 +20,12 @@ import android.content.Context; import android.os.Bundle; import android.os.Looper; import android.os.Message; + import androidx.fragment.app.FragmentActivity; + import android.util.Log; import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.api.AccountInfo; import com.google.android.gms.common.api.Api; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; @@ -41,10 +42,9 @@ public class GoogleApiClientImpl implements GoogleApiClient { private final Context context; private final Looper looper; - private final AccountInfo accountInfo; + private final ApiClientSettings clientSettings; private final Map apis = new HashMap(); - private final Map apiConnections = new HashMap(); - private final Handler handler; + private final Map apiConnections = new HashMap(); private final Set connectionCallbacks = new HashSet(); private final Set connectionFailedListeners = new HashSet(); private final int clientId; @@ -78,23 +78,20 @@ public class GoogleApiClientImpl implements GoogleApiClient { private int usageCounter = 0; private boolean shouldDisconnect = false; - public GoogleApiClientImpl(Context context, Looper looper, AccountInfo accountInfo, + public GoogleApiClientImpl(Context context, Looper looper, ApiClientSettings clientSettings, Map apis, Set connectionCallbacks, Set connectionFailedListeners, int clientId) { this.context = context; this.looper = looper; - this.handler = new Handler(looper); - this.accountInfo = accountInfo; + this.clientSettings = clientSettings; this.apis.putAll(apis); this.connectionCallbacks.addAll(connectionCallbacks); this.connectionFailedListeners.addAll(connectionFailedListeners); this.clientId = clientId; for (Api api : apis.keySet()) { - apiConnections.put(api, api.getBuilder().build(context, looper, - apis.get(api), accountInfo, baseConnectionCallbacks, - baseConnectionFailedListener)); + apiConnections.put(api, api.getBuilder().build(apis.get(api), context, looper, clientSettings, baseConnectionCallbacks, baseConnectionFailedListener)); } } @@ -111,7 +108,7 @@ public class GoogleApiClientImpl implements GoogleApiClient { return looper; } - public ApiConnection getApiConnection(Api api) { + public ApiClient getApiConnection(Api api) { return apiConnections.get(api); } @@ -141,7 +138,7 @@ public class GoogleApiClientImpl implements GoogleApiClient { Log.d(TAG, "Already connected/connecting, nothing to do"); return; } - for (ApiConnection connection : apiConnections.values()) { + for (ApiClient connection : apiConnections.values()) { if (!connection.isConnected()) { connection.connect(); } @@ -154,7 +151,7 @@ public class GoogleApiClientImpl implements GoogleApiClient { shouldDisconnect = true; } else { Log.d(TAG, "disconnect()"); - for (ApiConnection connection : apiConnections.values()) { + for (ApiClient connection : apiConnections.values()) { if (connection.isConnected()) { connection.disconnect(); } @@ -164,7 +161,7 @@ public class GoogleApiClientImpl implements GoogleApiClient { @Override public synchronized boolean isConnected() { - for (ApiConnection connection : apiConnections.values()) { + for (ApiClient connection : apiConnections.values()) { if (!connection.isConnected()) return false; } return true; @@ -172,7 +169,7 @@ public class GoogleApiClientImpl implements GoogleApiClient { @Override public synchronized boolean isConnecting() { - for (ApiConnection connection : apiConnections.values()) { + for (ApiClient connection : apiConnections.values()) { if (connection.isConnecting()) return true; } return false; @@ -220,23 +217,4 @@ public class GoogleApiClientImpl implements GoogleApiClient { public void unregisterConnectionFailedListener(OnConnectionFailedListener listener) { connectionFailedListeners.remove(listener); } - - private class Handler extends android.os.Handler { - private Handler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - if (msg.what == 0 && msg.obj instanceof Runnable) { - ((Runnable) msg.obj).run(); - } else { - super.handleMessage(msg); - } - } - - public void sendRunnable(Runnable runnable) { - sendMessage(obtainMessage(1, runnable)); - } - } } diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiManager.java b/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiManager.java new file mode 100644 index 00000000..1662ca31 --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/GoogleApiManager.java @@ -0,0 +1,180 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +import android.content.Context; +import android.os.Bundle; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApi; +import com.google.android.gms.tasks.TaskCompletionSource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GoogleApiManager { + private static GoogleApiManager instance; + private Context context; + private Map clientMap = new HashMap<>(); + private Map>> waitingApiCallMap = new HashMap<>(); + + private GoogleApiManager(Context context) { + this.context = context; + } + + public synchronized static GoogleApiManager getInstance(Context context) { + if (instance == null) instance = new GoogleApiManager(context); + return instance; + } + + private synchronized A clientForApi(GoogleApi api) { + ApiInstance apiInstance = new ApiInstance(api); + if (clientMap.containsKey(apiInstance)) { + return (A) clientMap.get(apiInstance); + } else { + ApiClient client = api.api.getBuilder().build(api.getOptions(), context, context.getMainLooper(), null, new ConnectionCallback(apiInstance), new ConnectionFailedListener(apiInstance)); + clientMap.put(apiInstance, client); + waitingApiCallMap.put(apiInstance, new ArrayList<>()); + return (A) client; + } + } + + public synchronized void scheduleTask(GoogleApi api, PendingGoogleApiCall apiCall, TaskCompletionSource completionSource) { + A client = clientForApi(api); + boolean connecting = client.isConnecting(); + boolean connected = client.isConnected(); + if (connected) { + apiCall.execute(client, completionSource); + } else { + waitingApiCallMap.get(new ApiInstance(api)).add(new WaitingApiCall((PendingGoogleApiCall) apiCall, completionSource)); + if (!connecting) { + client.connect(); + } + } + } + + private synchronized void onInstanceConnected(ApiInstance apiInstance, Bundle connectionHint) { + List> waitingApiCalls = waitingApiCallMap.get(apiInstance); + for (WaitingApiCall waitingApiCall : waitingApiCalls) { + waitingApiCall.execute(clientMap.get(apiInstance)); + } + waitingApiCalls.clear(); + } + + private synchronized void onInstanceSuspended(ApiInstance apiInstance, int cause) { + + } + + private synchronized void onInstanceFailed(ApiInstance apiInstance, ConnectionResult result) { + List> waitingApiCalls = waitingApiCallMap.get(apiInstance); + for (WaitingApiCall waitingApiCall : waitingApiCalls) { + waitingApiCall.failed(new RuntimeException(result.getErrorMessage())); + } + waitingApiCalls.clear(); + } + + private class ConnectionCallback implements ConnectionCallbacks { + private ApiInstance apiInstance; + + public ConnectionCallback(ApiInstance apiInstance) { + this.apiInstance = apiInstance; + } + + @Override + public void onConnected(Bundle connectionHint) { + onInstanceConnected(apiInstance, connectionHint); + } + + @Override + public void onConnectionSuspended(int cause) { + onInstanceSuspended(apiInstance, cause); + } + } + + private class ConnectionFailedListener implements OnConnectionFailedListener { + private ApiInstance apiInstance; + + public ConnectionFailedListener(ApiInstance apiInstance) { + this.apiInstance = apiInstance; + } + + @Override + public void onConnectionFailed(ConnectionResult result) { + onInstanceFailed(apiInstance, result); + } + } + + private static class WaitingApiCall { + private PendingGoogleApiCall apiCall; + private TaskCompletionSource completionSource; + + public WaitingApiCall(PendingGoogleApiCall apiCall, TaskCompletionSource completionSource) { + this.apiCall = apiCall; + this.completionSource = completionSource; + } + + public void execute(ApiClient client) { + apiCall.execute(client, completionSource); + } + + public void failed(Exception e) { + completionSource.setException(e); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WaitingApiCall that = (WaitingApiCall) o; + + if (apiCall != null ? !apiCall.equals(that.apiCall) : that.apiCall != null) return false; + return completionSource != null ? completionSource.equals(that.completionSource) : that.completionSource == null; + } + + @Override + public int hashCode() { + int result = apiCall != null ? apiCall.hashCode() : 0; + result = 31 * result + (completionSource != null ? completionSource.hashCode() : 0); + return result; + } + } + + private static class ApiInstance { + private Class apiClass; + private Api.ApiOptions apiOptions; + + public ApiInstance(Class apiClass, Api.ApiOptions apiOptions) { + this.apiClass = apiClass; + this.apiOptions = apiOptions; + } + + public ApiInstance(GoogleApi api) { + this(api.getClass(), api.getOptions()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ApiInstance that = (ApiInstance) o; + + if (apiClass != null ? !apiClass.equals(that.apiClass) : that.apiClass != null) return false; + return apiOptions != null ? apiOptions.equals(that.apiOptions) : that.apiOptions == null; + } + + @Override + public int hashCode() { + int result = apiClass != null ? apiClass.hashCode() : 0; + result = 31 * result + (apiOptions != null ? apiOptions.hashCode() : 0); + return result; + } + } +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/InstantGoogleApiCall.java b/play-services-base/src/main/java/org/microg/gms/common/api/InstantGoogleApiCall.java new file mode 100644 index 00000000..5e813d8b --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/InstantGoogleApiCall.java @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +import com.google.android.gms.tasks.TaskCompletionSource; + +public interface InstantGoogleApiCall extends PendingGoogleApiCall { + R execute(A client) throws Exception; + + @Override + default void execute(A client, TaskCompletionSource completionSource) { + try { + completionSource.setResult(execute(client)); + } catch (Exception e) { + completionSource.setException(e); + } + } +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/OnConnectionFailedListener.java b/play-services-base/src/main/java/org/microg/gms/common/api/OnConnectionFailedListener.java new file mode 100644 index 00000000..cd994235 --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/OnConnectionFailedListener.java @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +import android.app.Activity; + +import com.google.android.gms.common.ConnectionResult; + +public interface OnConnectionFailedListener { + /** + * Called when there was an error connecting the client to the service. + * + * @param result A {@link ConnectionResult} that can be used for resolving the error, and + * deciding what sort of error occurred. To resolve the error, the resolution + * must be started from an activity with a non-negative {@code requestCode} + * passed to {@link ConnectionResult#startResolutionForResult(Activity, int)}. + * Applications should implement {@link Activity#onActivityResult} in their + * Activity to call {@link #connect()} again if the user has resolved the + * issue (resultCode is {@link Activity#RESULT_OK}). + */ + void onConnectionFailed(ConnectionResult result); +} diff --git a/play-services-base/src/main/java/org/microg/gms/common/api/PendingGoogleApiCall.java b/play-services-base/src/main/java/org/microg/gms/common/api/PendingGoogleApiCall.java new file mode 100644 index 00000000..8c92abd7 --- /dev/null +++ b/play-services-base/src/main/java/org/microg/gms/common/api/PendingGoogleApiCall.java @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.common.api; + +import com.google.android.gms.tasks.TaskCompletionSource; + +public interface PendingGoogleApiCall { + void execute(A client, TaskCompletionSource completionSource); +} diff --git a/play-services-basement/build.gradle b/play-services-basement/build.gradle index 771415d5..474bebb1 100644 --- a/play-services-basement/build.gradle +++ b/play-services-basement/build.gradle @@ -30,8 +30,6 @@ android { buildToolsVersion "$androidBuildVersionTools" aidlPackageWhiteList "com/google/android/gms/common/api/Status.aidl" - aidlPackageWhiteList "com/google/android/gms/common/data/DataHolder.aidl" - aidlPackageWhiteList "com/google/android/gms/common/images/WebImage.aidl" aidlPackageWhiteList "com/google/android/gms/common/internal/ICancelToken.aidl" aidlPackageWhiteList "com/google/android/gms/common/server/FavaDiagnosticsEntity.aidl" aidlPackageWhiteList "com/google/android/gms/dynamic/IObjectWrapper.aidl" diff --git a/play-services-basement/src/main/java/org/microg/gms/common/Constants.java b/play-services-basement/src/main/java/org/microg/gms/common/Constants.java index 853eea71..c57c81ce 100644 --- a/play-services-basement/src/main/java/org/microg/gms/common/Constants.java +++ b/play-services-basement/src/main/java/org/microg/gms/common/Constants.java @@ -17,7 +17,7 @@ package org.microg.gms.common; public class Constants { - public static final int MAX_REFERENCE_VERSION = 19420 * 1000; + public static final int MAX_REFERENCE_VERSION = 202414 * 1000; public static final String GMS_PACKAGE_NAME = "com.google.android.gms"; public static final String GSF_PACKAGE_NAME = "com.mgoogle.android.gsf"; public static final String GMS_PACKAGE_SIGNATURE_SHA1 = "38918a453d07199354f8b19af05ec6562ced5788"; diff --git a/play-services-basement/src/main/java/org/microg/gms/common/GmsService.java b/play-services-basement/src/main/java/org/microg/gms/common/GmsService.java index 22eecc4a..7d65a911 100644 --- a/play-services-basement/src/main/java/org/microg/gms/common/GmsService.java +++ b/play-services-basement/src/main/java/org/microg/gms/common/GmsService.java @@ -88,6 +88,7 @@ public enum GmsService { PLUS_INTERNAL(70), SOURCE_DEVICE(75, "com.google.android.gms.smartdevice.d2d.SourceDeviceService.START"), TARGET_DEVICE(76, "com.google.android.gms.smartdevice.d2d.TargetDeviceService.START"), + APP_INVITE(77, "com.google.android.gms.appinvite.service.START"), TAP_AND_PAY(79, "com.google.android.gms.tapandpay.service.BIND"), ACCOUNTS(81, "com.google.android.gms.smartdevice.setup.accounts.AccountsService.START"), TRUST_AGENT(85, "com.google.android.gms.trustagent.StateApi.START"), @@ -98,6 +99,8 @@ public enum GmsService { GASS(116, "com.google.android.gms.gass.START"), WORK_ACCOUNT(120), AD_CACHE(123, "com.google.android.gms.ads.service.CACHE"), + DYNAMIC_LINKS(131, "com.google.firebase.dynamiclinks.service.START"), + NEARBY_EXPOSURE(236, "com.google.android.gms.nearby.exposurenotification.START"), ; public int SERVICE_ID; diff --git a/play-services-cast-api/build.gradle b/play-services-cast-api/build.gradle index b3d5f509..bdc679a1 100644 --- a/play-services-cast-api/build.gradle +++ b/play-services-cast-api/build.gradle @@ -37,4 +37,6 @@ android { dependencies { api project(':play-services-basement') + + api project(':play-services-base-api') } diff --git a/play-services-cast-framework-api/build.gradle b/play-services-cast-framework-api/build.gradle index db8f59e4..9db7c812 100644 --- a/play-services-cast-framework-api/build.gradle +++ b/play-services-cast-framework-api/build.gradle @@ -34,5 +34,7 @@ android { dependencies { api project(':play-services-basement') + + api project(':play-services-base-api') api project(':play-services-cast-api') } diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java b/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java new file mode 100644 index 00000000..33f7be44 --- /dev/null +++ b/play-services-cast/src/main/java/com/google/android/gms/cast/Cast.java @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.gms.cast; + +import android.os.Bundle; + +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.PendingResult; +import com.google.android.gms.common.api.Result; +import com.google.android.gms.common.api.Status; + +import org.microg.gms.cast.CastApiClientBuilder; +import org.microg.gms.cast.CastApiImpl; +import org.microg.gms.common.PublicApi; + +import java.io.IOException; + +@PublicApi +public final class Cast { + + /** + * A constant indicating that the Google Cast device is not the currently active video input. + */ + public static final int ACTIVE_INPUT_STATE_NO = 0; + + /** + * A constant indicating that it is not known (and/or not possible to know) whether the Google Cast device is + * the currently active video input. Active input state can only be reported when the Google Cast device is + * connected to a TV or AVR with CEC support. + */ + public static final int ACTIVE_INPUT_STATE_UNKNOWN = -1; + + /** + * A constant indicating that the Google Cast device is the currently active video input. + */ + public static final int ACTIVE_INPUT_STATE_YES = 1; + + /** + * A boolean extra for the connection hint bundle passed to + * {@link GoogleApiClient.ConnectionCallbacks#onConnected(Bundle)} that indicates that the connection was + * re-established, but the receiver application that was in use at the time of the connection loss is no longer + * running on the receiver. + */ + public static final String EXTRA_APP_NO_LONGER_RUNNING = "com.google.android.gms.cast.EXTRA_APP_NO_LONGER_RUNNING"; + + /** + * The maximum raw message length (in bytes) that is supported by a Cast channel. + */ + public static final int MAX_MESSAGE_LENGTH = 65536; + + /** + * The maximum length (in characters) of a namespace name. + */ + public static final int MAX_NAMESPACE_LENGTH = 128; + + /** + * A constant indicating that the Google Cast device is not currently in standby. + */ + public static final int STANDBY_STATE_NO = 0; + + /** + * A constant indicating that it is not known (and/or not possible to know) whether the Google Cast device is + * currently in standby. Standby state can only be reported when the Google Cast device is connected to a TV or + * AVR with CEC support. + */ + public static final int STANDBY_STATE_UNKNOWN = -1; + + /** + * A constant indicating that the Google Cast device is currently in standby. + */ + public static final int STANDBY_STATE_YES = 1; + + + /** + * Token to pass to {@link GoogleApiClient.Builder#addApi(Api)} to enable the Cast features. + */ + public static final Api API = new Api(new CastApiClientBuilder()); + + /** + * An implementation of the CastApi interface. The interface is used to interact with a cast device. + */ + public static final Cast.CastApi CastApi = new CastApiImpl(); + + private Cast() { + } + + public interface ApplicationConnectionResult extends Result { + ApplicationMetadata getApplicationMetadata(); + + String getApplicationStatus(); + + String getSessionId(); + + boolean getWasLaunched(); + } + + public interface CastApi { + int getActiveInputState(GoogleApiClient client); + + ApplicationMetadata getApplicationMetadata(GoogleApiClient client); + + String getApplicationStatus(GoogleApiClient client); + + int getStandbyState(GoogleApiClient client); + + double getVolume(GoogleApiClient client); + + boolean isMute(GoogleApiClient client); + + PendingResult joinApplication(GoogleApiClient client); + + PendingResult joinApplication(GoogleApiClient client, String applicationId, String sessionId); + + PendingResult joinApplication(GoogleApiClient client, String applicationId); + + PendingResult launchApplication(GoogleApiClient client, String applicationId, LaunchOptions launchOptions); + + PendingResult launchApplication(GoogleApiClient client, String applicationId); + + @Deprecated + PendingResult launchApplication(GoogleApiClient client, String applicationId, boolean relaunchIfRunning); + + PendingResult leaveApplication(GoogleApiClient client); + + void removeMessageReceivedCallbacks(GoogleApiClient client, String namespace) throws IOException; + + void requestStatus(GoogleApiClient client) throws IOException; + + PendingResult sendMessage(GoogleApiClient client, String namespace, String message); + + void setMessageReceivedCallbacks(GoogleApiClient client, String namespace, Cast.MessageReceivedCallback callbacks) throws IOException; + + void setMute(GoogleApiClient client, boolean mute) throws IOException; + + void setVolume(GoogleApiClient client, double volume) throws IOException; + + PendingResult stopApplication(GoogleApiClient client); + + PendingResult stopApplication(GoogleApiClient client, String sessionId); + } + + public static class CastOptions implements Api.ApiOptions.HasOptions { + private final CastDevice castDevice; + private final Listener castListener; + private final boolean verboseLoggingEnabled; + + public CastOptions(CastDevice castDevice, Listener castListener, boolean verboseLoggingEnabled) { + this.castDevice = castDevice; + this.castListener = castListener; + this.verboseLoggingEnabled = verboseLoggingEnabled; + } + + @Deprecated + public static Builder builder(CastDevice castDevice, Listener castListener) { + return new Builder(castDevice, castListener); + } + + public static class Builder { + private final CastDevice castDevice; + private final Listener castListener; + private boolean verboseLoggingEnabled; + + public Builder(CastDevice castDevice, Listener castListener) { + this.castDevice = castDevice; + this.castListener = castListener; + } + + public CastOptions build() { + return new CastOptions(castDevice, castListener, verboseLoggingEnabled); + } + + public Builder setVerboseLoggingEnabled(boolean verboseLoggingEnabled) { + this.verboseLoggingEnabled = verboseLoggingEnabled; + return this; + } + } + } + + public static class Listener { + public void onActiveInputStateChanged(int activeInputState) { + + } + + public void onApplicationDisconnected(int statusCode) { + + } + + public void onApplicationMetadataChanged(ApplicationMetadata applicationMetadata) { + + } + + public void onApplicationStatusChanged() { + + } + + public void onStandbyStateChanged(int standbyState) { + + } + + public void onVolumeChanged() { + + } + } + + public interface MessageReceivedCallback { + void onMessageReceived(CastDevice castDevice, String namespace, String message); + } +} diff --git a/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java b/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java new file mode 100644 index 00000000..30c20e73 --- /dev/null +++ b/play-services-cast/src/main/java/com/google/android/gms/cast/CastRemoteDisplay.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.gms.cast; + +import android.view.Display; + +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.Result; +import com.google.android.gms.common.api.Status; + +import org.microg.gms.cast.CastRemoteDisplayApiClientBuilder; +import org.microg.gms.cast.CastRemoteDisplayApiImpl; +import org.microg.gms.common.PublicApi; + +@PublicApi +public final class CastRemoteDisplay { + /** + * Token to pass to {@link GoogleApiClient.Builder#addApi(Api)} to enable the CastRemoteDisplay features. + */ + public static final Api API = new Api(new CastRemoteDisplayApiClientBuilder()); + + /** + * An implementation of the CastRemoteDisplayAPI interface. The interface is used to interact with a cast device. + */ + public static final CastRemoteDisplayApi CastApi = new CastRemoteDisplayApiImpl(); + + private CastRemoteDisplay() { + } + + public static final class CastRemoteDisplayOptions implements Api.ApiOptions.HasOptions { + private CastDevice castDevice; + private CastRemoteDisplaySessionCallbacks callbacks; + + private CastRemoteDisplayOptions(CastDevice castDevice, CastRemoteDisplaySessionCallbacks callbacks) { + this.castDevice = castDevice; + this.callbacks = callbacks; + } + + public static final class Builder { + private CastDevice castDevice; + private CastRemoteDisplaySessionCallbacks callbacks; + + public Builder(CastDevice castDevice, CastRemoteDisplaySessionCallbacks callbacks) { + this.castDevice = castDevice; + this.callbacks = callbacks; + } + + public CastRemoteDisplayOptions build() { + return new CastRemoteDisplayOptions(castDevice, callbacks); + } + } + } + + public interface CastRemoteDisplaySessionCallbacks { + void onRemoteDisplayEnded(Status status); + } + + public interface CastRemoteDisplaySessionResult extends Result { + Display getPresentationDisplay(); + } +} diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastApiClientBuilder.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastApiClientBuilder.java new file mode 100644 index 00000000..aba48971 --- /dev/null +++ b/play-services-cast/src/main/java/org/microg/gms/cast/CastApiClientBuilder.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * 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 org.microg.gms.cast; + +import android.content.Context; +import android.os.Looper; + +import com.google.android.gms.cast.Cast; + +import org.microg.gms.common.api.ApiClientBuilder; +import org.microg.gms.common.api.ApiClientSettings; +import org.microg.gms.common.api.ApiClient; +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; + +public class CastApiClientBuilder implements ApiClientBuilder { + @Override + public ApiClient build(Cast.CastOptions options, Context context, Looper looper, ApiClientSettings clientSettings, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) { + return new CastClientImpl(context, options, callbacks, connectionFailedListener); + } +} diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java new file mode 100644 index 00000000..8b6bd502 --- /dev/null +++ b/play-services-cast/src/main/java/org/microg/gms/cast/CastClientImpl.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * 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 org.microg.gms.cast; + +import android.content.Context; + +import com.google.android.gms.cast.Cast; + +import org.microg.gms.common.DummyApiClient; +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; + +public class CastClientImpl extends DummyApiClient { + public CastClientImpl(Context context, Cast.CastOptions options, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) { + } +} diff --git a/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiClientBuilder.java b/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiClientBuilder.java new file mode 100644 index 00000000..588d25c3 --- /dev/null +++ b/play-services-cast/src/main/java/org/microg/gms/cast/CastRemoteDisplayApiClientBuilder.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * 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 org.microg.gms.cast; + +import android.content.Context; +import android.os.Looper; + +import com.google.android.gms.cast.CastRemoteDisplay; + +import org.microg.gms.common.DummyApiClient; +import org.microg.gms.common.api.ApiClientBuilder; +import org.microg.gms.common.api.ApiClientSettings; +import org.microg.gms.common.api.ApiClient; +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; + +public class CastRemoteDisplayApiClientBuilder implements ApiClientBuilder { + @Override + public ApiClient build(CastRemoteDisplay.CastRemoteDisplayOptions options, Context context, Looper looper, ApiClientSettings clientSettings, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) { + return new DummyApiClient(); + } +} diff --git a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/DimmableIconPreference.java b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/DimmableIconPreference.java deleted file mode 100644 index 791cbd02..00000000 --- a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/DimmableIconPreference.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2014 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 org.microg.tools.ui; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.preference.Preference; -import androidx.preference.PreferenceViewHolder; - -/** - * A preference item that can dim the icon when it's disabled, either directly or because its parent - * is disabled. - */ -public class DimmableIconPreference extends Preference { - private static final int ICON_ALPHA_ENABLED = 255; - private static final int ICON_ALPHA_DISABLED = 102; - - private final CharSequence mContentDescription; - - public DimmableIconPreference(Context context) { - this(context, (AttributeSet) null); - } - - public DimmableIconPreference(Context context, AttributeSet attrs) { - super(context, attrs); - mContentDescription = null; - } - - public DimmableIconPreference(Context context, CharSequence contentDescription) { - super(context); - mContentDescription = contentDescription; - } - - protected boolean shouldDimIcon() { - return !isEnabled(); - } - - private void dimIcon(boolean dimmed) { - Drawable icon = getIcon(); - if (icon != null) { - icon.mutate().setAlpha(dimmed ? ICON_ALPHA_DISABLED : ICON_ALPHA_ENABLED); - setIcon(icon); - } - } - - @Override - public void onBindViewHolder(PreferenceViewHolder view) { - super.onBindViewHolder(view); - if (!TextUtils.isEmpty(mContentDescription)) { - final TextView titleView = (TextView) view.findViewById(android.R.id.title); - titleView.setContentDescription(mContentDescription); - } - ViewGroup.LayoutParams layoutParams = view.findViewById(R.id.icon_frame).getLayoutParams(); - if (layoutParams instanceof LinearLayout.LayoutParams) { - if (((LinearLayout.LayoutParams) layoutParams).leftMargin < 0) { - ((LinearLayout.LayoutParams) layoutParams).leftMargin = 0; - } - } - dimIcon(shouldDimIcon()); - } -} diff --git a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java index 950ac8b2..b2b33e3b 100644 --- a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java +++ b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java @@ -29,24 +29,22 @@ public abstract class SwitchBarResourceSettingsFragment extends ResourceSettings public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity(); - - switchBar = activity.getSwitchBar(); - switchBar.show(); - switchCompat = switchBar.getSwitch(); +// switchBar = activity.getSwitchBar(); +// switchBar.show(); +// switchCompat = switchBar.getSwitch(); } @Override public void onDestroyView() { super.onDestroyView(); - switchBar.hide(); +// switchBar.hide(); } @Override public void onResume() { super.onResume(); if (!listenerSetup) { - switchBar.addOnSwitchChangeListener(this); +// switchBar.addOnSwitchChangeListener(this); listenerSetup = true; } } @@ -54,7 +52,7 @@ public abstract class SwitchBarResourceSettingsFragment extends ResourceSettings @Override public void onPause() { if (listenerSetup) { - switchBar.removeOnSwitchChangeListener(this); +// switchBar.removeOnSwitchChangeListener(this); listenerSetup = false; } super.onPause(); diff --git a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/TintIconPreference.java b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/TintIconPreference.java deleted file mode 100644 index 05486b9c..00000000 --- a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/TintIconPreference.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.microg.tools.ui; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.TypedValue; - -import androidx.core.graphics.drawable.DrawableCompat; -import androidx.preference.PreferenceViewHolder; - -import static android.os.Build.VERSION.SDK_INT; -import static android.os.Build.VERSION_CODES.LOLLIPOP; - -public class TintIconPreference extends DimmableIconPreference { - - public TintIconPreference(Context context) { - this(context, (AttributeSet) null); - } - - public TintIconPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - private static int getThemeAccentColor(Context context) { - int colorAttr; - if (SDK_INT >= LOLLIPOP) { - colorAttr = android.R.attr.colorAccent; - } else { - //Get colorAccent defined for AppCompat - colorAttr = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName()); - } - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(colorAttr, outValue, true); - return outValue.data; - } - - @Override - public void onBindViewHolder(PreferenceViewHolder view) { - super.onBindViewHolder(view); - Drawable icon = getIcon(); - if (icon != null) { - DrawableCompat.setTint(icon, getThemeAccentColor(getContext())); - } - } -} diff --git a/play-services-core/microg-ui-tools/src/main/res/values-it/strings.xml b/play-services-core/microg-ui-tools/src/main/res/values-it/strings.xml new file mode 100644 index 00000000..52e85d46 --- /dev/null +++ b/play-services-core/microg-ui-tools/src/main/res/values-it/strings.xml @@ -0,0 +1,44 @@ + + + + + Strumenti interfaccia utente di microG + Licenza Apache 2.0, team di microG + + Versione %1$s + %1$s %2$s + Tutti i diritti sono riservati. + + Configurazione + + Auto-controllo + Verifica se il sistema è correttamente configurato per utilizzare microG. + + Autorizzazione concessa + Autorizzazione a %1$s: + Tocca qui per concedere l\'autorizzazione a %1$s. Negare l\'autorizzazione può comportare il funzionamento anomalo di altre applicazioni. + + microG UI Demo + Sommario + Versione v0.1.0 + Librerie incluse + + v4 Support Library + v7 appcompat Support Library + v7 preference Support Library + Licenza Apache 2.0, The Android Open Source Project + diff --git a/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteService.java b/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteService.java new file mode 100644 index 00000000..8270f78a --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteService.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 e Foundation + * + * 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 org.microg.gms.appinvite; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; +import android.os.RemoteException; + +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.internal.GetServiceRequest; +import com.google.android.gms.common.internal.IGmsCallbacks; + +import org.microg.gms.BaseService; +import org.microg.gms.common.GmsService; +import org.microg.gms.common.PackageUtils; + +import org.microg.gms.appinvite.AppInviteServiceImpl; + +public class AppInviteService extends BaseService { + private static final String TAG = "GmsAppInviteService"; + + public AppInviteService() { + super("GmsAppInviteSvc", GmsService.APP_INVITE); + } + + @Override + public void handleServiceRequest(IGmsCallbacks callback, GetServiceRequest request, GmsService service) throws RemoteException { + PackageUtils.getAndCheckCallingPackage(this, request.packageName); + Log.d(TAG, "callb: " + callback + " ; req: " + request + " ; serv: " + service); + + callback.onPostInitComplete(0, new AppInviteServiceImpl(this, request.packageName, request.extras), null); + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteServiceImpl.java new file mode 100644 index 00000000..e3bfe6d3 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/appinvite/AppInviteServiceImpl.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 e Foundation + * + * 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 org.microg.gms.appinvite; + +import android.os.Parcel; +import android.os.RemoteException; +import android.os.Bundle; +import android.app.Activity; +import android.util.Log; +import android.content.Context; +import android.content.Intent; + +import com.google.android.gms.common.api.Status; + +import com.google.android.gms.dynamic.IObjectWrapper; +import com.google.android.gms.dynamic.ObjectWrapper; + +import com.google.android.gms.appinvite.internal.IAppInviteService; +import com.google.android.gms.appinvite.internal.IAppInviteCallbacks; + + +public class AppInviteServiceImpl extends IAppInviteService.Stub { + private static final String TAG = "GmsAppInviteServImpl"; + + public AppInviteServiceImpl(Context context, String packageName, Bundle extras) { + } + + + @Override + public void updateInvitationOnInstall(IAppInviteCallbacks callback, String invitationId) throws RemoteException { + callback.onStatus(Status.SUCCESS); + } + + @Override + public void convertInvitation(IAppInviteCallbacks callback, String invitationId) throws RemoteException { + callback.onStatus(Status.SUCCESS); + } + + @Override + public void getInvitation(IAppInviteCallbacks callback) throws RemoteException { + callback.onStatusIntent(new Status(Activity.RESULT_CANCELED), null); + } + + + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (super.onTransact(code, data, reply, flags)) { + return true; + } + + Log.d(TAG, "onTransact [unknown]: " + code + ", " + data + ", " + flags); + return false; + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java new file mode 100644 index 00000000..f090c97e --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.checkin; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class CheckinPrefs implements SharedPreferences.OnSharedPreferenceChangeListener { + public static final String PREF_ENABLE_CHECKIN = "checkin_enable_service"; + private static CheckinPrefs INSTANCE; + + public static CheckinPrefs get(Context context) { + if (INSTANCE == null) { + if (context == null) return new CheckinPrefs(null); + INSTANCE = new CheckinPrefs(context.getApplicationContext()); + } + return INSTANCE; + } + + private SharedPreferences preferences; + private boolean checkinEnabled = false; + + private CheckinPrefs(Context context) { + if (context != null) { + preferences = PreferenceManager.getDefaultSharedPreferences(context); + preferences.registerOnSharedPreferenceChangeListener(this); + update(); + } + } + + private void update() { + checkinEnabled = preferences.getBoolean(PREF_ENABLE_CHECKIN, false); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + update(); + } + + public boolean isEnabled() { + return checkinEnabled; + } + + public static void setEnabled(Context context, boolean newStatus) { + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(PREF_ENABLE_CHECKIN, newStatus).commit(); + if (newStatus) { + context.sendOrderedBroadcast(new Intent(context, TriggerReceiver.class), null); + } + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java index b52a7133..123d76d3 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java @@ -31,7 +31,6 @@ import static org.microg.gms.checkin.CheckinService.EXTRA_FORCE_CHECKIN; public class TriggerReceiver extends WakefulBroadcastReceiver { private static final String TAG = "GmsCheckinTrigger"; - public static final String PREF_ENABLE_CHECKIN = "checkin_enable_service"; private static final long REGULAR_CHECKIN_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours @Override @@ -40,7 +39,7 @@ public class TriggerReceiver extends WakefulBroadcastReceiver { boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction()); ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_CHECKIN, false) || force) { + if (CheckinPrefs.get(context).isEnabled() || force) { if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()) && LastCheckinInfo.read(context).lastCheckin > System.currentTimeMillis() - REGULAR_CHECKIN_INTERVAL) { return; diff --git a/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksService.java b/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksService.java new file mode 100644 index 00000000..064d7ead --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksService.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2019 e Foundation + * + * 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 org.microg.gms.firebase.dynamiclinks; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; +import android.os.RemoteException; + +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.internal.GetServiceRequest; +import com.google.android.gms.common.internal.IGmsCallbacks; + +import org.microg.gms.BaseService; +import org.microg.gms.common.GmsService; +import org.microg.gms.common.PackageUtils; + +import org.microg.gms.firebase.dynamiclinks.DynamicLinksServiceImpl; + +public class DynamicLinksService extends BaseService { + private static final String TAG = "GmsDynamicLinksService"; + + public DynamicLinksService() { + super("GmsDynamicLinksSvc", GmsService.DYNAMIC_LINKS); + } + + @Override + public void handleServiceRequest(IGmsCallbacks callback, GetServiceRequest request, GmsService service) throws RemoteException { + PackageUtils.getAndCheckCallingPackage(this, request.packageName); + Log.d(TAG, "callb: " + callback + " ; req: " + request + " ; serv: " + service); + + callback.onPostInitComplete(0, new DynamicLinksServiceImpl(this, request.packageName, request.extras), null); + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksServiceImpl.java new file mode 100644 index 00000000..a9f970b5 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/firebase/dynamiclinks/DynamicLinksServiceImpl.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019 e Foundation + * + * 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 org.microg.gms.firebase.dynamiclinks; + +import android.os.Parcel; +import android.os.RemoteException; +import android.os.Bundle; +import android.util.Log; +import android.content.Context; +import android.content.Intent; + +import com.google.android.gms.common.api.Status; +import com.google.android.gms.common.api.CommonStatusCodes; + +import com.google.firebase.dynamiclinks.internal.IDynamicLinksService; +import com.google.firebase.dynamiclinks.internal.IDynamicLinksCallbacks; +import com.google.firebase.dynamiclinks.internal.DynamicLinkData; +import com.google.firebase.dynamiclinks.internal.ShortDynamicLink; + + +public class DynamicLinksServiceImpl extends IDynamicLinksService.Stub { + private static final String TAG = "GmsDynamicLinksServImpl"; + + public DynamicLinksServiceImpl(Context context, String packageName, Bundle extras) { + } + + + @Override + public void getInitialLink(IDynamicLinksCallbacks callback, String var2) throws RemoteException { + callback.onStatusDynamicLinkData(Status.SUCCESS, new DynamicLinkData()); + } + + + @Override + public void func2(IDynamicLinksCallbacks callback, Bundle var2) throws RemoteException { + Log.d(TAG, "func2: " + callback + ", " + var2); + callback.onStatusShortDynamicLink(Status.SUCCESS, new ShortDynamicLink()); + } + + + @Override + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (super.onTransact(code, data, reply, flags)) { + return true; + } + + Log.d(TAG, "onTransact [unknown]: " + code + ", " + data + ", " + flags); + return false; + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java b/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java index cb136365..b303aa0a 100644 --- a/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java +++ b/play-services-core/src/main/java/org/microg/gms/gcm/GcmPrefs.java @@ -17,6 +17,7 @@ package org.microg.gms.gcm; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.net.ConnectivityManager; import android.net.NetworkInfo; @@ -114,7 +115,7 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe public int getHeartbeatMsFor(String pref, boolean rawRoaming) { if (PREF_NETWORK_ROAMING.equals(pref) && (rawRoaming || networkRoaming != 0)) { - return networkRoaming * 6000; + return networkRoaming * 60000; } else if (PREF_NETWORK_MOBILE.equals(pref)) { if (networkMobile != 0) return networkMobile * 60000; else return learntMobile; @@ -197,6 +198,15 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe return isEnabled() && info != null && getHeartbeatMsFor(info) >= 0; } + public static void setEnabled(Context context, boolean newStatus) { + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, newStatus).commit(); + if (!newStatus) { + McsService.stop(context); + } else { + context.sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, context, TriggerReceiver.class)); + } + } + public boolean isGcmLogEnabled() { return gcmLogEnabled; } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java deleted file mode 100644 index 8a034b84..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2017 microG Project Team - * - * 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 org.microg.gms.ui; - -import android.os.Bundle; -import android.preference.PreferenceManager; - -import androidx.fragment.app.Fragment; - -import com.mgoogle.android.gms.R; - -import org.microg.tools.ui.AbstractSettingsActivity; -import org.microg.tools.ui.SwitchBarResourceSettingsFragment; - -import static org.microg.gms.checkin.TriggerReceiver.PREF_ENABLE_CHECKIN; - -public class CheckinFragment extends SwitchBarResourceSettingsFragment { - - public CheckinFragment() { - preferencesResource = R.xml.preferences_checkin; - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - switchBar.setChecked(PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(PREF_ENABLE_CHECKIN, true)); - } - - @Override - public void onSwitchBarChanged(boolean isChecked) { - PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putBoolean(PREF_ENABLE_CHECKIN, isChecked).apply(); - } - - - public static class AsActivity extends AbstractSettingsActivity { - public AsActivity() { - showHomeAsUp = true; - } - - @Override - protected Fragment getFragment() { - return new CheckinFragment(); - } - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java index 537fde3c..e167f26a 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java @@ -94,15 +94,4 @@ public class GcmAdvancedFragment extends ResourceSettingsFragment { } return (heartbeatMs / 60000) + " minutes"; } - - public static class AsActivity extends AbstractSettingsActivity { - public AsActivity() { - showHomeAsUp = true; - } - - @Override - protected Fragment getFragment() { - return new GcmAdvancedFragment(); - } - } } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java new file mode 100644 index 00000000..f3b62c1d --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * 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 org.microg.gms.ui; + +import androidx.fragment.app.Fragment; + +import com.google.android.gms.R; + +//import org.microg.nlp.Preferences; +import org.microg.tools.ui.AbstractDashboardActivity; + +public class SettingsDashboardActivity extends AbstractDashboardActivity { + + public SettingsDashboardActivity() { + preferencesResource = R.xml.preferences_start; + addCondition(Conditions.GCM_BATTERY_OPTIMIZATIONS); + addCondition(Conditions.PERMISSIONS); + } + + @Override + protected Fragment getFragment() { + return new SettingsFragment(); + } + +} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java new file mode 100644 index 00000000..482152e6 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java @@ -0,0 +1,97 @@ +package org.microg.gms.ui; + +import android.os.Bundle; + +import androidx.annotation.Nullable; +import androidx.navigation.fragment.NavHostFragment; + +import com.google.android.gms.R; + +import org.microg.gms.checkin.CheckinPrefs; +import org.microg.gms.gcm.GcmDatabase; +import org.microg.gms.gcm.GcmPrefs; +import org.microg.gms.snet.SafetyNetPrefs; +import org.microg.tools.ui.ResourceSettingsFragment; + +public class SettingsFragment extends ResourceSettingsFragment { + + public static final String PREF_ABOUT = "pref_about"; + public static final String PREF_GCM = "pref_gcm"; + public static final String PREF_SNET = "pref_snet"; + public static final String PREF_UNIFIEDNLP = "pref_unifiednlp"; + public static final String PREF_CHECKIN = "pref_checkin"; + + public SettingsFragment() { + preferencesResource = R.xml.preferences_start; + } + + @Override + public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { + super.onCreatePreferences(savedInstanceState, rootKey); + updateDetails(); + } + + @Override + public void onResume() { + super.onResume(); + updateDetails(); + } + + private void updateDetails() { + findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext()))); + findPreference(PREF_ABOUT).setOnPreferenceClickListener(preference -> { + NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openAbout); + return true; + }); + if (GcmPrefs.get(getContext()).isEnabled()) { + GcmDatabase database = new GcmDatabase(getContext()); + int regCount = database.getRegistrationList().size(); + database.close(); + findPreference(PREF_GCM).setSummary(getString(R.string.service_status_enabled_short) + " - " + getResources().getQuantityString(R.plurals.gcm_registered_apps_counter, regCount, regCount)); + } else { + findPreference(PREF_GCM).setSummary(R.string.service_status_disabled_short); + } + findPreference(PREF_GCM).setOnPreferenceClickListener(preference -> { + NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openGcmSettings); + return true; + }); + + if (SafetyNetPrefs.get(getContext()).isEnabled()) { + String snet_info = ""; + + if (SafetyNetPrefs.get(getContext()).isOfficial()) { + snet_info = getString(R.string.pref_snet_status_official_info); + } else if (SafetyNetPrefs.get(getContext()).isSelfSigned()) { + snet_info = getString(R.string.pref_snet_status_self_signed_info); + } else if (SafetyNetPrefs.get(getContext()).isThirdParty()) { + snet_info = getString(R.string.pref_snet_status_third_party_info); + } + + findPreference(PREF_SNET).setSummary(getString(R.string.service_status_enabled_short)); + } else { + findPreference(PREF_SNET).setSummary(R.string.service_status_disabled_short); + } + findPreference(PREF_SNET).setOnPreferenceClickListener(preference -> { + NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openSafetyNetSettings); + return true; + }); + +// Preferences unifiedNlPrefs = new Preferences(getContext()); +// int backendCount = TextUtils.isEmpty(unifiedNlPrefs.getLocationBackends()) ? 0 : +// Preferences.splitBackendString(unifiedNlPrefs.getLocationBackends()).length; +// backendCount += TextUtils.isEmpty(unifiedNlPrefs.getGeocoderBackends()) ? 0 : +// Preferences.splitBackendString(unifiedNlPrefs.getGeocoderBackends()).length; +// findPreference(PREF_UNIFIEDNLP).setSummary(getResources().getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount)); + findPreference(PREF_UNIFIEDNLP).setOnPreferenceClickListener(preference -> { + NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openUnifiedNlpSettings); + return true; + }); + + boolean checkinEnabled = CheckinPrefs.get(getContext()).isEnabled(); + findPreference(PREF_CHECKIN).setSummary(checkinEnabled ? R.string.service_status_enabled_short : R.string.service_status_disabled_short); + findPreference(PREF_CHECKIN).setOnPreferenceClickListener(preference -> { + NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openCheckinSettings); + return true; + }); + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java deleted file mode 100644 index f28aa901..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.microg.gms.ui; - -import androidx.fragment.app.Fragment; - -import org.microg.tools.ui.AbstractSettingsActivity; - -public class UnifiedBackendDetailsActivity extends AbstractSettingsActivity { - public UnifiedBackendDetailsActivity() { - showHomeAsUp = true; - } - - @Override - protected Fragment getFragment() { - return null; - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java deleted file mode 100644 index d9ec16fa..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.microg.gms.ui; - -import android.os.Bundle; -import android.util.Log; - -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; - -import org.microg.tools.ui.AbstractSettingsActivity; - -public class UnifiedBackendListActivity extends AppCompatActivity { - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } catch (Exception e) { - Log.w("GmsCoreSettingUi", e); - } - getSupportFragmentManager().beginTransaction().add(null, null).commit(); - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - finish(); - } -} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/provision/ProvisionService.kt b/play-services-core/src/main/kotlin/org/microg/gms/provision/ProvisionService.kt new file mode 100644 index 00000000..9cfd43c1 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/provision/ProvisionService.kt @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.provision + +import android.app.Service +import android.content.Intent +import android.os.Bundle +import android.util.Log +import androidx.lifecycle.LifecycleService +import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.delay +import org.microg.gms.checkin.CheckinPrefs +import org.microg.gms.gcm.GcmPrefs +import org.microg.gms.snet.SafetyNetPrefs + +class ProvisionService : LifecycleService() { + private fun Bundle.getBooleanOrNull(key: String): Boolean? { + return if (containsKey(key)) getBoolean(key) else null + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + super.onStartCommand(intent, flags, startId) + lifecycleScope.launchWhenStarted { + intent?.extras?.let { + val s = it.keySet().map { key -> "$key = ${it[key]}" }.joinToString(", ") + Log.d(TAG, "Provisioning: $s") + } + + intent?.extras?.getBooleanOrNull("checkin_enabled")?.let { CheckinPrefs.setEnabled(this@ProvisionService, it) } + intent?.extras?.getBooleanOrNull("gcm_enabled")?.let { GcmPrefs.setEnabled(this@ProvisionService, it) } + intent?.extras?.getBooleanOrNull("safetynet_enabled")?.let { SafetyNetPrefs.get(this@ProvisionService).isEnabled = it } + // What else? + + delay(2 * 1000) // Wait 2 seconds to give provisioning some extra time + stopSelfResult(startId) + } + return Service.START_NOT_STICKY + } + + companion object { + private const val TAG = "GmsProvision" + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt new file mode 100644 index 00000000..97bcca1d --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.content.Context +import android.util.DisplayMetrics +import android.widget.ImageView +import androidx.preference.Preference +import androidx.preference.PreferenceViewHolder + +class AppIconPreference(context: Context) : Preference(context) { + override fun onBindViewHolder(holder: PreferenceViewHolder?) { + super.onBindViewHolder(holder) + val icon = holder?.findViewById(android.R.id.icon) + if (icon is ImageView) { + icon.adjustViewBounds = true + icon.scaleType = ImageView.ScaleType.CENTER_INSIDE + icon.maxHeight = (32.0 * context.resources.displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT).toInt() + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt new file mode 100644 index 00000000..5cece629 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import com.google.android.gms.R +import com.google.android.gms.databinding.DeviceRegistrationFragmentBinding +import org.microg.gms.checkin.CheckinPrefs + +class DeviceRegistrationFragment : Fragment(R.layout.device_registration_fragment) { + private lateinit var binding: DeviceRegistrationFragmentBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DeviceRegistrationFragmentBinding.inflate(inflater, container, false) + binding.switchBarCallback = object : PreferenceSwitchBarCallback { + override fun onChecked(newStatus: Boolean) { + CheckinPrefs.setEnabled(context, newStatus) + binding.checkinEnabled = newStatus + } + } + return binding.root + } + + override fun onResume() { + super.onResume() + lifecycleScope.launchWhenResumed { + binding.checkinEnabled = CheckinPrefs.get(context).isEnabled + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt new file mode 100644 index 00000000..b1f53234 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.os.Handler +import android.text.format.DateUtils +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat +import com.google.android.gms.R +import org.microg.gms.checkin.CheckinPrefs +import org.microg.gms.checkin.LastCheckinInfo + +class DeviceRegistrationPreferencesFragment : PreferenceFragmentCompat() { + private lateinit var statusCategory: PreferenceCategory + private lateinit var status: Preference + private val handler = Handler() + private val updateRunnable = Runnable { updateStatus() } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_device_registration) + } + + override fun onBindPreferences() { + statusCategory = preferenceScreen.findPreference("prefcat_device_registration_status") ?: statusCategory + status = preferenceScreen.findPreference("pref_device_registration_status") ?: status + } + + override fun onResume() { + super.onResume() + updateStatus() + } + + override fun onPause() { + super.onPause() + handler.removeCallbacks(updateRunnable) + } + + private fun updateStatus() { + handler.postDelayed(updateRunnable, UPDATE_INTERVAL) + statusCategory.isVisible = CheckinPrefs.get(context).isEnabled + val checkinInfo = LastCheckinInfo.read(requireContext()) + status.summary = if (checkinInfo.lastCheckin > 0) { + getString(R.string.checkin_last_registration, DateUtils.getRelativeTimeSpanString(checkinInfo.lastCheckin, System.currentTimeMillis(), 0)) + } else { + getString(R.string.checkin_not_registered) + } + } + + companion object { + private const val UPDATE_INTERVAL = 1000L + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt new file mode 100644 index 00000000..b66f1119 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +interface PreferenceSwitchBarCallback { + fun onChecked(newStatus: Boolean) +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt new file mode 100644 index 00000000..a55b007d --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt @@ -0,0 +1,115 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.text.format.DateUtils +import androidx.appcompat.content.res.AppCompatResources +import androidx.core.os.bundleOf +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat +import com.google.android.gms.R +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.microg.gms.gcm.GcmDatabase + +class PushNotificationAllAppsFragment : PreferenceFragmentCompat() { + private lateinit var database: GcmDatabase + private lateinit var registered: PreferenceCategory + private lateinit var unregistered: PreferenceCategory + private lateinit var registeredNone: Preference + private lateinit var unregisteredNone: Preference + private lateinit var progress: Preference + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + database = GcmDatabase(context) + } + + override fun onResume() { + super.onResume() + updateContent() + } + + override fun onPause() { + super.onPause() + database.close() + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_push_notifications_all_apps) + registered = preferenceScreen.findPreference("prefcat_push_apps_registered") ?: registered + unregistered = preferenceScreen.findPreference("prefcat_push_apps_unregistered") ?: unregistered + registeredNone = preferenceScreen.findPreference("pref_push_apps_registered_none") ?: registeredNone + unregisteredNone = preferenceScreen.findPreference("pref_push_apps_unregistered_none") ?: unregisteredNone + progress = preferenceScreen.findPreference("pref_push_apps_all_progress") ?: progress + } + + private fun updateContent() { + lifecycleScope.launchWhenResumed { + val context = requireContext() + val apps = withContext(Dispatchers.IO) { + val res = database.appList.map { app -> + try { + app to context.packageManager.getApplicationInfo(app.packageName, 0) + } catch (ignored: Exception) { + app to null + } + }.map { (app, applicationInfo) -> + val pref = AppIconPreference(context) + pref.title = applicationInfo?.loadLabel(context.packageManager) ?: app.packageName + pref.summary = when { + app.lastMessageTimestamp > 0 -> getString(R.string.gcm_last_message_at, DateUtils.getRelativeTimeSpanString(app.lastMessageTimestamp)) + else -> null + } + pref.icon = applicationInfo?.loadIcon(context.packageManager) + ?: AppCompatResources.getDrawable(context, android.R.mipmap.sym_def_app_icon) + pref.onPreferenceClickListener = Preference.OnPreferenceClickListener { + findNavController().navigate(R.id.openGcmAppDetailsFromAll, bundleOf( + "package" to app.packageName + )) + true + } + pref.key = "pref_push_app_" + app.packageName + pref to (database.getRegistrationsByApp(app.packageName)) + }.sortedBy { + it.first.title.toString().toLowerCase() + }.mapIndexed { idx, pair -> + pair.first.order = idx + pair + } + database.close() + res + } + registered.removeAll() + registered.isVisible = true + unregistered.removeAll() + unregistered.isVisible = true + + var hadRegistered = false + var hadUnregistered = false + + for (pair in apps) { + if (pair.second.isEmpty()) { + unregistered.addPreference(pair.first) + hadUnregistered = true + } else { + registered.addPreference(pair.first) + hadRegistered = true + } + } + + registeredNone.isVisible = !hadRegistered + unregisteredNone.isVisible = !hadUnregistered + if (!hadRegistered) registered.addPreference(registeredNone) + if (!hadUnregistered) unregistered.addPreference(unregisteredNone) + progress.isVisible = false + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt new file mode 100644 index 00000000..5699ec07 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.provider.Settings +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.content.res.AppCompatResources +import androidx.fragment.app.Fragment +import androidx.fragment.app.findFragment +import androidx.lifecycle.lifecycleScope +import com.google.android.gms.R +import com.google.android.gms.databinding.PushNotificationAppFragmentBinding + + +class PushNotificationAppFragment : Fragment(R.layout.push_notification_fragment) { + lateinit var binding: PushNotificationAppFragmentBinding + val packageName: String? + get() = arguments?.getString("package") + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = PushNotificationAppFragmentBinding.inflate(inflater, container, false) + binding.callbacks = object : PushNotificationAppFragmentCallbacks { + override fun onAppClicked() { + val intent = Intent() + intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS + val uri: Uri = Uri.fromParts("package", packageName, null) + intent.data = uri + context!!.startActivity(intent) + } + } + childFragmentManager.findFragmentById(R.id.sub_preferences)?.arguments = arguments + return binding.root + } + + override fun onResume() { + super.onResume() + lifecycleScope.launchWhenResumed { + val pm = requireContext().packageManager + val applicationInfo = packageName?.let { pm.getApplicationInfo(it, 0) } + binding.appName = applicationInfo?.loadLabel(pm)?.toString() ?: packageName + binding.appIcon = applicationInfo?.loadIcon(pm) + ?: AppCompatResources.getDrawable(requireContext(), android.R.mipmap.sym_def_app_icon) + } + } +} + +interface PushNotificationAppFragmentCallbacks { + fun onAppClicked() +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt new file mode 100644 index 00000000..b327349e --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt @@ -0,0 +1,134 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.text.format.DateUtils +import androidx.appcompat.app.AlertDialog +import androidx.lifecycle.lifecycleScope +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.TwoStatePreference +import com.google.android.gms.R +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.microg.gms.gcm.GcmDatabase +import org.microg.gms.gcm.PushRegisterManager + +class PushNotificationAppPreferencesFragment : PreferenceFragmentCompat() { + private lateinit var wakeForDelivery: TwoStatePreference + private lateinit var allowRegister: TwoStatePreference + private lateinit var status: Preference + private lateinit var unregister: Preference + private lateinit var unregisterCat: PreferenceCategory + + private lateinit var database: GcmDatabase + private val packageName: String? + get() = arguments?.getString("package") + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_push_notifications_app) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + database = GcmDatabase(context) + } + + override fun onBindPreferences() { + wakeForDelivery = preferenceScreen.findPreference("pref_push_app_wake_for_delivery") ?: wakeForDelivery + allowRegister = preferenceScreen.findPreference("pref_push_app_allow_register") ?: allowRegister + unregister = preferenceScreen.findPreference("pref_push_app_unregister") ?: unregister + unregisterCat = preferenceScreen.findPreference("prefcat_push_app_unregister") ?: unregisterCat + status = preferenceScreen.findPreference("pref_push_app_status") ?: status + wakeForDelivery.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + database.setAppWakeForDelivery(packageName, newValue as Boolean) + database.close() + true + } + allowRegister.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + val enabled = newValue as? Boolean ?: return@OnPreferenceChangeListener false + if (!enabled) { + val registrations = packageName?.let { database.getRegistrationsByApp(it) } ?: emptyList() + if (registrations.isNotEmpty()) { + showUnregisterConfirm(R.string.gcm_unregister_after_deny_message) + } + } + database.setAppAllowRegister(packageName, enabled) + database.close() + true + } + unregister.onPreferenceClickListener = Preference.OnPreferenceClickListener { + showUnregisterConfirm(R.string.gcm_unregister_confirm_message) + true + } + } + + + private fun showUnregisterConfirm(unregisterConfirmDesc: Int) { + val pm = requireContext().packageManager + val applicationInfo = packageName?.let { pm.getApplicationInfo(it, 0) } + AlertDialog.Builder(requireContext()) + .setTitle(getString(R.string.gcm_unregister_confirm_title, applicationInfo?.loadLabel(pm) + ?: packageName)) + .setMessage(unregisterConfirmDesc) + .setPositiveButton(android.R.string.yes) { _, _ -> unregister() } + .setNegativeButton(android.R.string.no) { _, _ -> }.show() + } + + private fun unregister() { + lifecycleScope.launchWhenResumed { + withContext(Dispatchers.IO) { + for (registration in database.getRegistrationsByApp(packageName)) { + PushRegisterManager.unregister(context, registration.packageName, registration.signature, null, null) + } + } + updateDetails() + } + } + + override fun onResume() { + super.onResume() + updateDetails() + } + + private fun updateDetails() { + lifecycleScope.launchWhenResumed { + val app = packageName?.let { database.getApp(it) } + wakeForDelivery.isChecked = app?.wakeForDelivery ?: true + allowRegister.isChecked = app?.allowRegister ?: true + val registrations = packageName?.let { database.getRegistrationsByApp(it) } ?: emptyList() + unregisterCat.isVisible = registrations.isNotEmpty() + + val sb = StringBuilder() + if ((app?.totalMessageCount ?: 0L) == 0L) { + sb.append(getString(R.string.gcm_no_message_yet)) + } else { + sb.append(getString(R.string.gcm_messages_counter, app?.totalMessageCount, app?.totalMessageBytes)) + if (app?.lastMessageTimestamp != 0L) { + sb.append("\n").append(getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(context, app?.lastMessageTimestamp ?: 0L, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME))) + } + } + for (registration in registrations) { + sb.append("\n") + if (registration.timestamp == 0L) { + sb.append(getString(R.string.gcm_registered)) + } else { + sb.append(getString(R.string.gcm_registered_since, DateUtils.getRelativeDateTimeString(context, registration.timestamp, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME))) + } + } + status.summary = sb.toString() + + database.close() + } + } + + override fun onPause() { + super.onPause() + database.close() + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt new file mode 100644 index 00000000..6345c62b --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ +package org.microg.gms.ui + +import android.os.Bundle +import android.view.* +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import com.google.android.gms.R +import com.google.android.gms.databinding.PushNotificationFragmentBinding +import org.microg.gms.checkin.CheckinPrefs +import org.microg.gms.gcm.GcmPrefs + +class PushNotificationFragment : Fragment(R.layout.push_notification_fragment) { + lateinit var binding: PushNotificationFragmentBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = PushNotificationFragmentBinding.inflate(inflater, container, false) + binding.switchBarCallback = object : PreferenceSwitchBarCallback { + override fun onChecked(newStatus: Boolean) { + GcmPrefs.setEnabled(context, newStatus) + binding.gcmEnabled = newStatus + } + } + return binding.root + } + + override fun onResume() { + super.onResume() + lifecycleScope.launchWhenResumed { + binding.gcmEnabled = GcmPrefs.get(context).isEnabled + binding.checkinEnabled = CheckinPrefs.get(context).isEnabled + } + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + setHasOptionsMenu(true) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + MENU_ADVANCED -> { + findNavController().navigate(R.id.openGcmAdvancedSettings) + true + } + else -> super.onOptionsItemSelected(item) + } + } + + companion object { + private const val MENU_ADVANCED = Menu.FIRST + } +} + diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt new file mode 100644 index 00000000..9021ffb5 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.os.Handler +import android.text.format.DateUtils +import androidx.core.os.bundleOf +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import androidx.preference.Preference +import androidx.preference.PreferenceCategory +import androidx.preference.PreferenceFragmentCompat +import com.google.android.gms.R +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.microg.gms.gcm.GcmDatabase +import org.microg.gms.gcm.GcmPrefs +import org.microg.gms.gcm.McsService + +class PushNotificationPreferencesFragment : PreferenceFragmentCompat() { + private lateinit var pushStatusCategory: PreferenceCategory + private lateinit var pushStatus: Preference + private lateinit var pushApps: PreferenceCategory + private lateinit var pushAppsAll: Preference + private lateinit var pushAppsNone: Preference + private lateinit var database: GcmDatabase + private val handler = Handler() + private val updateRunnable = Runnable { updateStatus() } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + database = GcmDatabase(context) + } + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_push_notifications) + } + + override fun onBindPreferences() { + pushStatusCategory = preferenceScreen.findPreference("prefcat_push_status") ?: pushStatusCategory + pushStatus = preferenceScreen.findPreference("pref_push_status") ?: pushStatus + pushApps = preferenceScreen.findPreference("prefcat_push_apps") ?: pushApps + pushAppsAll = preferenceScreen.findPreference("pref_push_apps_all") ?: pushAppsAll + pushAppsNone = preferenceScreen.findPreference("pref_push_apps_none") ?: pushAppsNone + pushAppsAll.onPreferenceClickListener = Preference.OnPreferenceClickListener { + findNavController().navigate(R.id.openAllGcmApps) + true + } + } + + override fun onResume() { + super.onResume() + updateStatus() + updateContent() + } + + override fun onPause() { + super.onPause() + database.close() + handler.removeCallbacks(updateRunnable) + } + + private fun updateStatus() { + handler.postDelayed(updateRunnable, UPDATE_INTERVAL) + pushStatusCategory.isVisible = GcmPrefs.get(context).isEnabled + pushStatus.summary = if (McsService.isConnected()) { + getString(R.string.gcm_network_state_connected, DateUtils.getRelativeTimeSpanString(McsService.getStartTimestamp(), System.currentTimeMillis(), 0)) + } else { + getString(R.string.gcm_network_state_disconnected) + } + } + + private fun updateContent() { + lifecycleScope.launchWhenResumed { + val context = requireContext() + val (apps, showAll) = withContext(Dispatchers.IO) { + val apps = database.appList.sortedByDescending { it.lastMessageTimestamp } + val res = apps.map { app -> + try { + app to context.packageManager.getApplicationInfo(app.packageName, 0) + } catch (ignored: Exception) { + null + } + }.filterNotNull().take(3).mapIndexed { idx, (app, applicationInfo) -> + val pref = AppIconPreference(context) + pref.order = idx + pref.title = applicationInfo.loadLabel(context.packageManager) + pref.icon = applicationInfo.loadIcon(context.packageManager) + pref.onPreferenceClickListener = Preference.OnPreferenceClickListener { + findNavController().navigate(R.id.openGcmAppDetails, bundleOf( + "package" to app.packageName + )) + true + } + pref.key = "pref_push_app_" + app.packageName + pref + }.let { it to (it.size < apps.size) } + database.close() + res + } + pushAppsAll.isVisible = showAll + pushApps.removeAll() + for (app in apps) { + pushApps.addPreference(app) + } + if (showAll) { + pushApps.addPreference(pushAppsAll) + } else if (apps.isEmpty()) { + pushApps.addPreference(pushAppsNone) + } + } + } + + companion object { + private const val UPDATE_INTERVAL = 1000L + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt new file mode 100644 index 00000000..b611a1ac --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import android.view.* +import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController +import com.google.android.gms.R +import com.google.android.gms.databinding.SafetyNetFragmentBinding +import org.microg.gms.checkin.CheckinPrefs +import org.microg.gms.snet.SafetyNetPrefs + +class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) { + + private lateinit var binding: SafetyNetFragmentBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = SafetyNetFragmentBinding.inflate(inflater, container, false) + binding.switchBarCallback = object : PreferenceSwitchBarCallback { + override fun onChecked(newStatus: Boolean) { + SafetyNetPrefs.get(requireContext()).isEnabled = newStatus + binding.safetynetEnabled = newStatus + } + } + return binding.root + } + + override fun onResume() { + super.onResume() + binding.checkinEnabled = CheckinPrefs.get(requireContext()).isEnabled + binding.safetynetEnabled = SafetyNetPrefs.get(requireContext()).isEnabled + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + setHasOptionsMenu(true) + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + MENU_ADVANCED -> { + findNavController().navigate(R.id.openSafetyNetAdvancedSettings) + true + } + else -> super.onOptionsItemSelected(item) + } + } + + companion object { + private const val MENU_ADVANCED = Menu.FIRST + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt new file mode 100644 index 00000000..2a4b4ab2 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.ui + +import android.os.Bundle +import androidx.preference.PreferenceFragmentCompat +import com.google.android.gms.R + +class SafetyNetPreferencesFragment : PreferenceFragmentCompat() { + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + addPreferencesFromResource(R.xml.preferences_safetynet) + } +} diff --git a/play-services-core/src/main/res/drawable-ldpi/add_account.png b/play-services-core/src/main/res/drawable-ldpi/add_account.png deleted file mode 100644 index c84ada96..00000000 Binary files a/play-services-core/src/main/res/drawable-ldpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-mdpi/add_account.png b/play-services-core/src/main/res/drawable-mdpi/add_account.png deleted file mode 100644 index 7cbdff98..00000000 Binary files a/play-services-core/src/main/res/drawable-mdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xhdpi/add_account.png b/play-services-core/src/main/res/drawable-xhdpi/add_account.png deleted file mode 100644 index bf14e0a7..00000000 Binary files a/play-services-core/src/main/res/drawable-xhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxhdpi/add_account.png b/play-services-core/src/main/res/drawable-xxhdpi/add_account.png deleted file mode 100644 index 53264c28..00000000 Binary files a/play-services-core/src/main/res/drawable-xxhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png b/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png deleted file mode 100644 index a03e2eaa..00000000 Binary files a/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml b/play-services-core/src/main/res/drawable/ic_add_account.xml similarity index 92% rename from play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml rename to play-services-core/src/main/res/drawable/ic_add_account.xml index aa8b898a..1ff91a0e 100644 --- a/play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml +++ b/play-services-core/src/main/res/drawable/ic_add_account.xml @@ -2,6 +2,7 @@ @@ -10,4 +11,4 @@ - \ No newline at end of file + diff --git a/play-services-core/src/main/res/drawable/gcm_bell.xml b/play-services-core/src/main/res/drawable/ic_cloud_bell.xml similarity index 79% rename from play-services-core/src/main/res/drawable/gcm_bell.xml rename to play-services-core/src/main/res/drawable/ic_cloud_bell.xml index 89a1cae4..0f41c719 100644 --- a/play-services-core/src/main/res/drawable/gcm_bell.xml +++ b/play-services-core/src/main/res/drawable/ic_cloud_bell.xml @@ -1,11 +1,12 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + android:pathData="M 12 4 C 9.11 4 6.5996094 5.6392969 5.3496094 8.0292969 C 2.3396094 8.3592969 0 10.9 0 14 A 6 6 0 0 0 6 20 L 19 20 A 5 5 0 0 0 24 15 C 24 12.36 21.949609 10.219297 19.349609 10.029297 C 18.669609 6.5892969 15.64 4 12 4 z M 12 7.5 A 0.5 0.5 0 0 1 12.5 8 L 12.5 8.5390625 C 13.92 8.7790625 15 10.015 15 11.5 L 15 14.5 L 16.5 16 L 7.5 16 L 9 14.5 L 9 11.5 C 9 10.015 10.08 8.7790625 11.5 8.5390625 L 11.5 8 A 0.5 0.5 0 0 1 12 7.5 z M 11 16.5 L 13 16.5 A 1 1 0 0 1 12 17.5 A 1 1 0 0 1 11 16.5 z" /> + diff --git a/play-services-core/src/main/res/drawable/device_login.xml b/play-services-core/src/main/res/drawable/ic_device_login.xml similarity index 58% rename from play-services-core/src/main/res/drawable/device_login.xml rename to play-services-core/src/main/res/drawable/ic_device_login.xml index f1a4e1e4..c0bce50c 100644 --- a/play-services-core/src/main/res/drawable/device_login.xml +++ b/play-services-core/src/main/res/drawable/ic_device_login.xml @@ -1,11 +1,12 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + android:pathData="M10,17.25V14H3V10H10V6.75L15.25,12L10,17.25M8,2H17A2,2 0 0,1 19,4V20A2,2 0 0,1 17,22H8A2,2 0 0,1 6,20V16H8V20H17V4H8V8H6V4A2,2 0 0,1 8,2Z" /> + diff --git a/play-services-core/src/main/res/drawable/ic_expand_apps.xml b/play-services-core/src/main/res/drawable/ic_expand_apps.xml new file mode 100644 index 00000000..20634f05 --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_expand_apps.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_info_outline.xml b/play-services-core/src/main/res/drawable/ic_info_outline.xml new file mode 100644 index 00000000..8e049cce --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_info_outline.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_map_marker.xml b/play-services-core/src/main/res/drawable/ic_map_marker.xml new file mode 100644 index 00000000..b97f8b8d --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_map_marker.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/layout/ask_gcm.xml b/play-services-core/src/main/res/layout/ask_gcm.xml index 9d3e8be8..a5c20212 100644 --- a/play-services-core/src/main/res/layout/ask_gcm.xml +++ b/play-services-core/src/main/res/layout/ask_gcm.xml @@ -48,7 +48,7 @@ android:layout_width="36dip" android:layout_height="36dip" android:scaleType="fitCenter" - android:src="@drawable/gcm_bell" + android:src="@drawable/ic_cloud_bell" android:tint="?attr/colorAccent"> diff --git a/play-services-core/src/main/res/layout/device_registration_fragment.xml b/play-services-core/src/main/res/layout/device_registration_fragment.xml new file mode 100644 index 00000000..0f0648dc --- /dev/null +++ b/play-services-core/src/main/res/layout/device_registration_fragment.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/preference_category_no_label.xml b/play-services-core/src/main/res/layout/preference_category_no_label.xml new file mode 100644 index 00000000..31b8b654 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_category_no_label.xml @@ -0,0 +1,9 @@ + + + + diff --git a/play-services-core/src/main/res/layout/preference_progress_bar.xml b/play-services-core/src/main/res/layout/preference_progress_bar.xml new file mode 100644 index 00000000..bd0eb7e0 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_progress_bar.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/play-services-core/src/main/res/layout/preference_switch_bar.xml b/play-services-core/src/main/res/layout/preference_switch_bar.xml new file mode 100644 index 00000000..08ad6530 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_switch_bar.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/push_notification_app_fragment.xml b/play-services-core/src/main/res/layout/push_notification_app_fragment.xml new file mode 100644 index 00000000..4f63f961 --- /dev/null +++ b/play-services-core/src/main/res/layout/push_notification_app_fragment.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/push_notification_fragment.xml b/play-services-core/src/main/res/layout/push_notification_fragment.xml new file mode 100644 index 00000000..e9611b83 --- /dev/null +++ b/play-services-core/src/main/res/layout/push_notification_fragment.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/safety_net_fragment.xml b/play-services-core/src/main/res/layout/safety_net_fragment.xml new file mode 100644 index 00000000..e97378ae --- /dev/null +++ b/play-services-core/src/main/res/layout/safety_net_fragment.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/settings_root_activity.xml b/play-services-core/src/main/res/layout/settings_root_activity.xml new file mode 100644 index 00000000..a592e38d --- /dev/null +++ b/play-services-core/src/main/res/layout/settings_root_activity.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/play-services-core/src/main/res/navigation/nav_settings.xml b/play-services-core/src/main/res/navigation/nav_settings.xml new file mode 100644 index 00000000..4a7a5246 --- /dev/null +++ b/play-services-core/src/main/res/navigation/nav_settings.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/values-de/strings.xml b/play-services-core/src/main/res/values-de/strings.xml index 4091cef0..9ba93404 100644 --- a/play-services-core/src/main/res/values-de/strings.xml +++ b/play-services-core/src/main/res/values-de/strings.xml @@ -102,7 +102,7 @@ Dies kann einige Minuten dauern." Einige Apps registrieren sich nicht automatisch erneut und haben keine Möglichkeit dies manuell anzustoßen. Diese Apps funktionieren eventuell nach dem abmelden nicht mehr richtig.\nFortsetzen? Du hast einer App die Erlaubnis der Registrierung entzogen, die bereits registriert ist.\nWillst du diese App jetzt auch abmelden damit sie zukünftig keine Push-Nachrichten erhält? Nachrichten: %1$d (%2$d bytes) - Aktueller Zustand: Nicht verbunden - Aktueller Zustand: Verbunden seit %1$s + Nicht verbunden + Verbunden seit %1$s diff --git a/play-services-core/src/main/res/values-fr/strings.xml b/play-services-core/src/main/res/values-fr/strings.xml index 2c30a07f..5b3fb20b 100644 --- a/play-services-core/src/main/res/values-fr/strings.xml +++ b/play-services-core/src/main/res/values-fr/strings.xml @@ -100,7 +100,7 @@ Ceci peut prendre plusieurs minutes." Certaines applications ne se réenregistrent pas et/ou ne fournisse pas de moyens de le faire manuellement. Ces applications peuvent ne plus fonctionner correctement après le désenregistrement.\nContinuer ? Vous avez empêché une application déjà enregistrée de s’enregistrer pour recevoir des notifications push.\nVoulez-vous la désenregistrer maintenant pour qu’elle ne reçoive plus de notifications push à l’avenir ? Messages : %1$d (%2$d octets) - Status actuel : Déconnecté - Status actuel : Connecté depuis %1$s + Déconnecté + Connecté depuis %1$s diff --git a/play-services-core/src/main/res/values-it/permissions.xml b/play-services-core/src/main/res/values-it/permissions.xml new file mode 100644 index 00000000..b2c5d580 --- /dev/null +++ b/play-services-core/src/main/res/values-it/permissions.xml @@ -0,0 +1,42 @@ + + + + + Tutti i servizi Google + Permette alle applicazioni di accedere a tutti i servizi Google mediante l\'account Google. + + Servizi Android + Permette alle applicazioni di accedere ai servizi Android mediante l\'account Google. + Google AdSense + Permette alle applicazioni di accedere a Google AdSense mediante l\'account Google. + Google AdWords + Permette alle applicazioni di accedere a Google AdWords mediante l\'account Google. + Google App Engine + Permette alle applicazioni di accedere a Google App Engine mediante l\'account Google. + Google Blogger + Permette alle applicazioni di accedere a Google Blogger mediante l\'account Google. + Calendario Google + Permette alle applicazioni di accedere al calendario di Google mediante l\'account Google. + Contatti Google + Permette alle applicazioni di accedere ai Contatti Google mediante l\'account Google. + Dodgeball + Permette alle applicazioni di accedere a Dodgeball mediante l\'account Google. + Google Finance + Permette alle applicazioni di accedere a Google Finance mediante l\'account Google. + Google Base + Permette alle applicazioni di accedere a Google base mediante l\'account Google. + diff --git a/play-services-core/src/main/res/values-it/plurals.xml b/play-services-core/src/main/res/values-it/plurals.xml new file mode 100644 index 00000000..413e2a0a --- /dev/null +++ b/play-services-core/src/main/res/values-it/plurals.xml @@ -0,0 +1,35 @@ + + + + + + %1$d fornitore configurato. + %1$d fornitori configurati. + + + %1$d applicazione registrata + %1$d applicazioni registrate + + + Un permesso necessario al corretto funzionamento di microG non è stato concesso. + Più permessi necessari al corretto funzionamento di microG non sono stati concessi. + + + Richiedi il permesso mancante + Richiedi i permessi mancanti + + diff --git a/play-services-core/src/main/res/values-it/strings.xml b/play-services-core/src/main/res/values-it/strings.xml new file mode 100644 index 00000000..52676d09 --- /dev/null +++ b/play-services-core/src/main/res/values-it/strings.xml @@ -0,0 +1,183 @@ + + + + Servizi microG + Impostazioni di microG + Configurazione di microG + + Giusto un secondo… + Google + Continuando autorizzi questa applicazione e Google ad usare le tue informazioni in accordo con i rispettivi termini di servizio e politiche di riservatezza. + %1$s vorrebbe: + %1$s vorrebbe utilizzare: + Gestione dell\'account Google + Ci dispiace… + "Un\'applicazione sul tuo dispositivo sta tentando di accedere all\'account Google. + +Se ciò era intenzionale, utilizzate il pulsante Accedi per collegarti alla pagina di autenticazione di Google, in caso contrario utilizza il pulsante Cancella per tornare all\'applicazione che ha aperto questa finestra di dialogo." + Accedere + "Il tuo dispositivo sta stabilendo la connessione con i server di Google per autenticarti. + +Questa operazione può richiedere alcuni secondi." + "Non disponi di una connessione ad internet. + +Potrebbe trattarsi di un disservizio temporaneo oppure non essere il tuo dispositivo Android fornito di connessione dati. Riprova quando connessi ad una rete cellulare o ad una rete Wi-Fi." + "C\è stato un problema di comunicazione con i server di Google. + +Try again later." + "Il tuo dispositivo sta comunicando con i server di Google per salvare le informazioni sull\'account. + +Questa operazione può richiedere alcuni minuti." + Permetti + Nega + Autenticazione necessaria + %1$s necessita della tua autorizzazione ad accedere all\'account Google. + + Ascolta la trasmissione di stati interni + Ascolta messaggi C2DM + Invia messaggi C2DM ad altre applicazioni + Scambia messaggi e riceve notifiche di sincronizzazione dai server Google + Accesso esteso ai servizi Google + + Registrazione del dispositivo + Messaggistica cloud + SafetyNet + + Disabilitato + Abilitato + Automatico + Manuale + + Impostazioni avanzate + Nessuno + + Google Play Games + %1$s vorrebbe usare Play Games + Per usare Play Games è necessario installare l\'applicazione di Play Games. L\'applicazione può continuare ad essere usata senza Play Games, ma è possibile che funzioni in modo anomalo. + + Seleziona un luogo + Non è ancora possibile selezionare un luogo. + Seleziona questo luogo + Luoghi vicini + (%1$.7f, %2$.7f) + + microG: Il permesso di %1$s è mancante + + Reti mobili + Wi-Fi + Roaming + Altre reti + + + + Supporto alla falsificazione della firma + Pacchetti installati + Sistema + + Il sistema supporta la falsificazione della firma: + La tua ROM non dispone del supporto nativo per la falsificazione della firma. Puoi comunque utilizzare Xposed o altri sistemi per garantire la falsificazione della firma. Consulta la documentazione su quali ROM supportino la falsificazione della firma e su come utlizzare microG sulle ROM che non la supportano. + Il sistema garantisce la falsificazione della firma: + Questo è un indice sintomatico del fatto che la ROM attuale supporta la falsificazione della firma, ma richiede azioni ulteriori per attivarla. Consulta la documentazione su quali operazioni siano necessarie. + Il sistema falsifica la firma: + Consulta la documentazione su quali operazioni siano necessarie. + + Play Services (GmsCore) + Play Store (Phonesky) + Services Framework (GSF) + %1$s installato: + Installa l\'applicazione %1$s oppure un\'altra compatibile. Consulta la documentazione su quali applicazioni siano compatibili. + %1$s ha la firma corretta: + O l\'applicazione %1$s non è compatibile, oppure la falsificazione della firma non è attiva per essa. Consulta la documentazione su quali applicazioni e ROM siano compatibili. + + Ottimizzazioni della batteria ignorate: + Tocca qui per disabilitare le ottimizzazioni della batteria. Non selezionare questa opzione potrebbe comportare il malfunzionamento delle applicazioni. + + + + Informazioni + Componenti + Configurazione + Servizi Google + Servizi di Localizzazione + Modalità operativa + Servizi + Sperimentale + + Ottimizzazioni della batteria abilitate + Hai abilitato il servizio di messaggistica cloud di Google, tuttavia le ottimizzazioni della batteria sono abilitate per microG. Al fine di garantire la ricezione delle notisfiche push, dovresti slezionare l\'opzione per ignorare le ottimizzazioni della batteria. + Ignora ottimizzazioni + Permesso mancante + + Preferenze dell\'account + Informazioni personali e riservatezza + Accesso e sicurezza + + Dai fiducia a Google per i permessi alle applicazioni + Quando disabilitato, viene interpellato l\'utente prima che ogni richiesta di autorizzazione da parte delle applicazioni venga inviata a Google. Alcune applicazioni potrebbero fallire nell\'utilizzare l\'account Google se questa opzione è disabilitata. + Autorizza le applicazioni a visualizzare gli account + Quando abilitata tutte le applicazioni su questo dispositivo saranno in grado di visualizzare gli indirizzi di posta elettronica dell\'account Google senza autorizzazione preventiva. + + Registra il tuo dispositivo ai servizi Google e crea un identificativo univoco. microG estrapola bit di identidicazione piuttosto che il nome dell\'account Google dai dati di registrazione. + + Impostazioni avanzate + + Account + Aggiungi un account Google + Il servizio di messaggistica cloud di Google è un fornitore di notifiche push utilizzato da molte applicazioni di terze parti. Per poterlo utlizzare devi abilitare la registrazione del dispositivo. + Intervallo di aggiornamento del servizio di messaggistica cloud di Google + L\'intervallo temporale, espresso in secondi, utilizzato dal sistema per contattare i serve di Google. Aumentare questo intervallo ridurrà il consumo di batteria, tuttavia potrebbe causare ritardi nella ricezione delle notifiche push.\nDeprecato, verrà rimpiazzato in versioni future. + Applicazioni che utilizzano il servizio di messaggistica cloud di Google + Lista delle applicazioni attualmente registrate al servizio di messaggistica cloud di Google: + Conferma le nuove applicazioni + Interroga l\'utente prima di registrare una nuova applicazione per le notifiche push. + Intervallo di ping: %1$s + + A proposito di microG + Informazioni sulla versione e sulle librerie utilizzate + + Errore durante la de-registrazione + Non più installata + De-registrazione + Non registrata + Nessun messaggio ricevuto fino ad ora + Ultimo messaggio: %1$s + Registrata + Registrata da: %1$s + De-registrazione %1$s? + Alcune applicazioni non rinnovano automaticamente la registrazione e/o non forniscono un\'opzione per farlo manualmente. Queste applicazioni potrebbero non funzionare correttamente a seguito della de-registrazione.\nContinuare? + Hai negato ad una applicazione già registrata di registrarsi alle notifiche push.\nDesideri de-registrarla così che non riceva più notifiche push in futuro? + Messaggi: %1$d (%2$d bytes) + Disconnesso + Connesso da %1$s + + SafetyNet di Google è un sistema di certificazione dispositivo che ne garantisce la sicurezza e la compatibilità con Android CTS. Alcune applicazioni utlizzano SafetyNet per ragioni di sicurezza o come prerequisito per la protezione da manomissione.\n\nmicroG contiene una implementazione libera di SafetyNet, tuttavia i server ufficiali richiedono che le richieste SafetyNet siano firmate utilizzando il sistema proprietario DroidGuard. Una versione contenitore di DroidGuard è disponibile come applicazione “DroidGuard Helper”. + + Provare l\'attestazione SafetyNet + + Usa i server ufficiali + Richiede un sistema senza privilegi di superutente e microG DroidGuard Helper installato + Server ufficiale + Usa i server di terzi parti + I server di terze parti potrebbero essere in grado di rispondere alle richieste di SafetyNet senza la firma di DroidGuard + Server di terze parti + URL del server personalizzato + URL completo del server personalizzato rispondente alle richieste di attestazione SafetyNet + Usa certificato auto-firmato + Anziché richiedere un server, firma localmente le risposte SafetyNet utlizzando un certificato auto-firmato. La maggior parte delle applicazioni rifiuteranno l\'uso di risposte auto-firmate. + Certificato auto-firmato + + diff --git a/play-services-core/src/main/res/values-pl/strings.xml b/play-services-core/src/main/res/values-pl/strings.xml index 73275c51..41ba8f67 100644 --- a/play-services-core/src/main/res/values-pl/strings.xml +++ b/play-services-core/src/main/res/values-pl/strings.xml @@ -100,7 +100,5 @@ To zajmie kilka minut. Niektóre aplikacje nie rejestrują się automatycznie ponownie lub nie posiadają opcji do zrobienia tego ręcznie. Takie aplikacje po wyrejestrowaniu mogą nie działać prawidłowo.\nCzy chcesz kontynuować? Odmówiłeś już zarejestrowanej aplikacji zarejestrować się w usłudze powiadomień ‘push’.\nCzy chcesz ją wyrejestrować, aby nie otrzymywała powiadomień ‘push’ w przyszłości? Wiadomości: %1$d (%2$d bajtów) - Obecny stan: rozłączony - Obecny stan: połączony od %1$s diff --git a/play-services-core/src/main/res/values-pt-rBR/strings.xml b/play-services-core/src/main/res/values-pt-rBR/strings.xml index 3da3b6a4..3f7e7d07 100644 --- a/play-services-core/src/main/res/values-pt-rBR/strings.xml +++ b/play-services-core/src/main/res/values-pt-rBR/strings.xml @@ -90,7 +90,7 @@ Isso pode demorar alguns minutos." Algumas aplicações não registam automaticamente e/ou não fornecem uma opção para fazê-lo manualmente. Esses aplicativos podem não funcionar corretamente após o cancelamento do registro.\nContinuar? Você negou um app para se registrar para notificações push que já está registrado.\nDeseja cancelar o registo agora para que não receba mensagens de envio no futuro? Mensagens: %1$d (%2$d bytes) - Estado atual: desconectado - Estado atual: Conectado desde %1$s + Desconectado + Conectado desde %1$s - + diff --git a/play-services-core/src/main/res/values-ru/strings.xml b/play-services-core/src/main/res/values-ru/strings.xml index 0aadc115..2b352e09 100644 --- a/play-services-core/src/main/res/values-ru/strings.xml +++ b/play-services-core/src/main/res/values-ru/strings.xml @@ -110,7 +110,5 @@ "Некоторые приложение автоматически не перепривязываются и/или не предоставляют возможности сделать это вручную. Такие приложения могут работать некорректно после отвязки.\nПродолжить?" Вы запретили push-уведомления для приложения, которое уже привязано.\nВы хотите отвязать его сейчас чтобы больше не получать от него push-уведомлений? Уведомлений: %1$d (%2$d bytes) - Текущий статус: Отключен - Текущий статус: Подключен %1$s diff --git a/play-services-core/src/main/res/values-sr/strings.xml b/play-services-core/src/main/res/values-sr/strings.xml index a50a96b6..b47bf436 100644 --- a/play-services-core/src/main/res/values-sr/strings.xml +++ b/play-services-core/src/main/res/values-sr/strings.xml @@ -90,7 +90,5 @@ Неке се апликације не пријављују поново аутоматски и/или не пружају могућност да се то уради ручно. Ове апликације можда неће радити исправно након одјављивања.\nДа наставим? Нисте дозволили апликацији да се пријави на гурана обавештења а која је већ пријављена.\nЖелите ли да је одјавите сада тако да убудуће не прима гурана обавештења? Порука: %1$d (%2$d бајта) - Тренутно стање: неповезан - Тренутно стање: повезан %1$s - + diff --git a/play-services-core/src/main/res/values-uk/strings.xml b/play-services-core/src/main/res/values-uk/strings.xml index 4da1093b..d7e23259 100644 --- a/play-services-core/src/main/res/values-uk/strings.xml +++ b/play-services-core/src/main/res/values-uk/strings.xml @@ -107,7 +107,5 @@ Деякі додатки автоматично не прив\'язуються або/та не дозволяють зробити це вручну. Такі додатки можуть робити некоректно після відв\'язування.\nПродовжити? Ви заборонили додатку push-повідомлення, який вже був прив\'язаний.\nВи бажаєте відв\'язати його зараз, аби більше не отримувати від нього push-повідомлень? Повідомлень: %1$d (%2$d байт) - Поточний стан: Відключено - Поточний стан: Під\'єднано від %1$s diff --git a/play-services-core/src/main/res/values-zh-rTW/strings.xml b/play-services-core/src/main/res/values-zh-rTW/strings.xml index 6bcc9d57..b2c90114 100644 --- a/play-services-core/src/main/res/values-zh-rTW/strings.xml +++ b/play-services-core/src/main/res/values-zh-rTW/strings.xml @@ -93,7 +93,5 @@ 您拒絕了一個已經註冊的程式去註冊接收推送通知。 您是否想取消註冊讓它未來不再收到推送通知? 已接收訊息:%1$d個(%2$d位元組〉 - 現在狀態:未連接 - 現在狀態:自%1$s連接至今 diff --git a/play-services-core/src/main/res/xml/preferences_device_registration.xml b/play-services-core/src/main/res/xml/preferences_device_registration.xml new file mode 100644 index 00000000..92c2023f --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_device_registration.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_gcm_advanced.xml b/play-services-core/src/main/res/xml/preferences_gcm_advanced.xml index 449e2d60..bc14d3dd 100644 --- a/play-services-core/src/main/res/xml/preferences_gcm_advanced.xml +++ b/play-services-core/src/main/res/xml/preferences_gcm_advanced.xml @@ -25,7 +25,7 @@ + android:title="@string/prefcat_push_networks_title"> - \ No newline at end of file + diff --git a/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml b/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml deleted file mode 100644 index 3dc8186a..00000000 --- a/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications.xml b/play-services-core/src/main/res/xml/preferences_push_notifications.xml new file mode 100644 index 00000000..e9384ea5 --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml b/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml new file mode 100644 index 00000000..9a93c8db --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml b/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml new file mode 100644 index 00000000..907fd211 --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-location/src/main/java/com/google/android/gms/location/ActivityRecognition.java b/play-services-location/src/main/java/com/google/android/gms/location/ActivityRecognition.java new file mode 100644 index 00000000..f8f11656 --- /dev/null +++ b/play-services-location/src/main/java/com/google/android/gms/location/ActivityRecognition.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017 microG Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.gms.location; + +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApiClient.Builder; + +import org.microg.gms.location.ActivityRecognitionApiClientBuilder; +import org.microg.gms.location.ActivityRecognitionApiImpl; + +/** + * The main entry point for activity recognition integration. + */ +public class ActivityRecognition { + public static final String CLIENT_NAME = "activity_recognition"; + + /** + * Token to pass to {@link Builder#addApi(Api)} to enable ContextServices. + */ + public static final Api API = new Api(new ActivityRecognitionApiClientBuilder()); + + /** + * Entry point to the activity recognition APIs. + */ + public static final ActivityRecognitionApi ActivityRecognitionApi = new ActivityRecognitionApiImpl(); +} diff --git a/play-services-location/src/main/java/com/google/android/gms/location/FusedLocationProviderClient.java b/play-services-location/src/main/java/com/google/android/gms/location/FusedLocationProviderClient.java new file mode 100644 index 00000000..a391c720 --- /dev/null +++ b/play-services-location/src/main/java/com/google/android/gms/location/FusedLocationProviderClient.java @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.android.gms.location; + +import android.content.Context; +import android.location.Location; + +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApi; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; + +import org.microg.gms.common.PublicApi; +import org.microg.gms.common.api.InstantGoogleApiCall; +import org.microg.gms.common.api.PendingGoogleApiCall; +import org.microg.gms.location.LocationClientImpl; + +@PublicApi +public class FusedLocationProviderClient extends GoogleApi { + @PublicApi(exclude = true) + public FusedLocationProviderClient(Context context) { + super(context, LocationServices.API); + } + + public Task flushLocations() { + return scheduleTask(new PendingGoogleApiCall() { + @Override + public void execute(LocationClientImpl client, TaskCompletionSource completionSource) { + completionSource.setResult(null); + } + }); + } + + public Task getLastLocation() { + return scheduleTask((InstantGoogleApiCall) LocationClientImpl::getLastLocation); + } + + +} diff --git a/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionApiClientBuilder.java b/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionApiClientBuilder.java new file mode 100644 index 00000000..1d22bd14 --- /dev/null +++ b/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionApiClientBuilder.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2017 microG Project Team + * + * 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 org.microg.gms.location; + +import android.content.Context; +import android.os.Looper; + +import com.google.android.gms.common.api.Api.ApiOptions.NoOptions; + +import org.microg.gms.common.api.ApiClientBuilder; +import org.microg.gms.common.api.ApiClientSettings; +import org.microg.gms.common.api.ApiClient; +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; + +public class ActivityRecognitionApiClientBuilder implements ApiClientBuilder { + @Override + public ApiClient build(NoOptions options, Context context, Looper looper, ApiClientSettings clientSettings, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) { + return new ActivityRecognitionClientImpl(context, callbacks, connectionFailedListener); + } +} diff --git a/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionClientImpl.java b/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionClientImpl.java new file mode 100644 index 00000000..f48aa489 --- /dev/null +++ b/play-services-location/src/main/java/org/microg/gms/location/ActivityRecognitionClientImpl.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 microG Project Team + * + * 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 org.microg.gms.location; + +import android.app.PendingIntent; +import android.content.Context; +import android.os.RemoteException; + +import org.microg.gms.common.api.ConnectionCallbacks; +import org.microg.gms.common.api.OnConnectionFailedListener; + +public class ActivityRecognitionClientImpl extends GoogleLocationManagerClient { + public ActivityRecognitionClientImpl(Context context, ConnectionCallbacks callbacks, OnConnectionFailedListener connectionFailedListener) { + super(context, callbacks, connectionFailedListener); + } + + public void requestActivityUpdates(long detectionIntervalMillis, PendingIntent callbackIntent) throws RemoteException { + getServiceInterface().requestActivityUpdates(detectionIntervalMillis, true, callbackIntent); + } + + public void removeActivityUpdates(PendingIntent callbackIntent) throws RemoteException { + getServiceInterface().removeActivityUpdates(callbackIntent); + } +} diff --git a/play-services-tasks/build.gradle b/play-services-tasks/build.gradle index 7d1eb81f..bb8662f8 100644 --- a/play-services-tasks/build.gradle +++ b/play-services-tasks/build.gradle @@ -1,17 +1,6 @@ /* - * Copyright 2013-2015 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 */ apply plugin: 'com.android.library' diff --git a/play-services-tasks/src/main/AndroidManifest.xml b/play-services-tasks/src/main/AndroidManifest.xml index 68340930..c7b833fe 100644 --- a/play-services-tasks/src/main/AndroidManifest.xml +++ b/play-services-tasks/src/main/AndroidManifest.xml @@ -1,18 +1,7 @@ diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationToken.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationToken.java new file mode 100644 index 00000000..00563c5b --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationToken.java @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; + +@PublicApi +public abstract class CancellationToken { + /** + * Checks if cancellation has been requested from the {@link CancellationTokenSource}. + * + * @return {@code true} if cancellation is requested, {@code false} otherwise + */ + public abstract boolean isCancellationRequested(); + + /** + * Adds an {@link OnTokenCanceledListener} to this {@link CancellationToken}. + * + * @param listener the listener that will fire once the cancellation request succeeds. + */ + public abstract CancellationToken onCanceledRequested(OnTokenCanceledListener listener); +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationTokenSource.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationTokenSource.java new file mode 100644 index 00000000..044b0466 --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/CancellationTokenSource.java @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; +import org.microg.gms.tasks.CancellationTokenImpl; + +/** + * Creates a new {@link CancellationToken} or cancels one that has already created. There is a 1:1 {@link CancellationTokenSource} to {@link CancellationToken} relationship. + *

+ * To create a {@link CancellationToken}, create a {@link CancellationTokenSource} first and then call {@link #getToken()} to get the {@link CancellationToken} for this {@link CancellationTokenSource}. + * + * @see CancellationToken + */ +@PublicApi +public class CancellationTokenSource { + private CancellationTokenImpl token = new CancellationTokenImpl(); + + /** + * Creates a new {@link CancellationTokenSource} instance. + */ + public CancellationTokenSource() { + } + + /** + * Cancels the {@link CancellationToken} if cancellation has not been requested yet. + */ + public void cancel() { + token.cancel(); + } + + /** + * Gets the {@link CancellationToken} for this {@link CancellationTokenSource}. + * + * @return the {@link CancellationToken} that can be passed to asynchronous {@link Task} to cancel the Task. + */ + public CancellationToken getToken() { + return token; + } +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Continuation.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Continuation.java index 26b69a81..7057ca71 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Continuation.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Continuation.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/DuplicateTaskCompletionException.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/DuplicateTaskCompletionException.java new file mode 100644 index 00000000..81eaa700 --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/DuplicateTaskCompletionException.java @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; + +/** + * An exception indicating that something attempted to set a result, exception, or cancellation on a {@link Task} that was already completed. + */ +@PublicApi +public class DuplicateTaskCompletionException extends IllegalStateException { + + private DuplicateTaskCompletionException(String s) { + super(s); + } + + /** + * Creates a DuplicateTaskCompletionException from a {@link Task}. + * + * The {@link Task} must be complete. + */ + public static DuplicateTaskCompletionException of(Task task) { + if (!task.isComplete()) throw new IllegalStateException("Task is not yet completed"); + return new DuplicateTaskCompletionException("Task is already completed"); + } +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCanceledListener.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCanceledListener.java new file mode 100644 index 00000000..32fd7b0f --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCanceledListener.java @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; + +/** + * Listener called when a {@link Task} is canceled. + */ +@PublicApi +public interface OnCanceledListener { + /** + * Called when the Task is canceled successfully. + */ + public abstract void onCanceled(); +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCompleteListener.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCompleteListener.java index 2035472c..7cff8dcf 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCompleteListener.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnCompleteListener.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnFailureListener.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnFailureListener.java index c6e1124b..e9391531 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnFailureListener.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnFailureListener.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnSuccessListener.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnSuccessListener.java index f6e6fbdd..5460c0a9 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnSuccessListener.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnSuccessListener.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnTokenCanceledListener.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnTokenCanceledListener.java new file mode 100644 index 00000000..0ad2d686 --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/OnTokenCanceledListener.java @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; + +/** + * Listener called when a {@link CancellationToken} is canceled successfully. + * + * @see CancellationToken#onCanceledRequested(OnTokenCanceledListener) + */ +@PublicApi +public interface OnTokenCanceledListener { + /** + * Called when the {@link CancellationToken} is canceled successfully. + */ + void onCanceled(); +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/RuntimeExecutionException.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/RuntimeExecutionException.java index 99482115..a15dfbe3 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/RuntimeExecutionException.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/RuntimeExecutionException.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/SuccessContinuation.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/SuccessContinuation.java new file mode 100644 index 00000000..3feb598e --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/SuccessContinuation.java @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import org.microg.gms.common.PublicApi; + +/** + * A function that is called to continue execution then a {@link Task} succeeds. + * @see Task#onSuccessTask + */ +@PublicApi +public interface SuccessContinuation { + /** + * Returns the result of applying this SuccessContinuation to Task. + *

+ * The SuccessContinuation only happens then the Task is successful. If the previous Task fails, the onSuccessTask continuation will be skipped and failure listeners will be invoked. + * + * @param result the result of completed Task + * @throws Exception if the result couldn't be produced + */ + Task then(TResult result) throws Exception; +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Task.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Task.java index b9963173..f7223779 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Task.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Task.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; @@ -31,6 +23,42 @@ public abstract class Task { public Task() { } + /** + * Adds a listener that is called if the Task is canceled. + *

+ * The listener will be called on main application thread. If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added. + * + * @return this Task + */ + public Task addOnCanceledListener(OnCanceledListener listener) { + throw new UnsupportedOperationException("addOnCanceledListener is not implemented"); + } + + /** + * Adds a listener that is called if the Task is canceled. + *

+ * If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added. + * + * @param executor the executor to use to call the listener + * @return this Task + */ + public Task addOnCanceledListener(Executor executor, OnCanceledListener listener) { + throw new UnsupportedOperationException("addOnCanceledListener is not implemented"); + } + + /** + * Adds an Activity-scoped listener that is called if the Task is canceled. + *

+ * The listener will be called on main application thread. If the Task has already been canceled, a call to the listener will be immediately scheduled. If multiple listeners are added, they will be called in the order in which they were added. + *

+ * The listener will be automatically removed during {@link Activity#onStop()}. + * + * @return this Task + */ + public Task addOnCanceledListener(Activity activity, OnCanceledListener listener) { + throw new UnsupportedOperationException("addOnCanceledListener is not implemented"); + } + /** * Adds a listener that is called when the Task completes. *

@@ -184,7 +212,7 @@ public abstract class Task { * @param executor the executor to use to call the Continuation * @see Continuation#then(Task) */ - public Task continueWithTask(Executor executor, Continuation> var2) { + public Task continueWithTask(Executor executor, Continuation> continuation) { throw new UnsupportedOperationException("continueWithTask is not implemented"); } @@ -211,6 +239,11 @@ public abstract class Task { */ public abstract TResult getResult(Class exceptionType) throws X; + /** + * Returns {@code true} if the Task is canceled; {@code false} otherwise. + */ + public abstract boolean isCanceled(); + /** * Returns {@code true} if the Task is complete; {@code false} otherwise. */ @@ -221,4 +254,29 @@ public abstract class Task { */ public abstract boolean isSuccessful(); + /** + * Returns a new Task that will be completed with the result of applying the specified SuccessContinuation to this Task when this Task completes successfully. If the previous Task fails, the onSuccessTask completion will be skipped and failure listeners will be invoked. + *

+ * The SuccessContinuation will be called on the main application thread. + *

+ * If the previous Task is canceled, the returned Task will also be canceled and the SuccessContinuation would not execute. + * + * @see SuccessContinuation#then + */ + public Task onSuccessTask(SuccessContinuation successContinuation) { + throw new UnsupportedOperationException("onSuccessTask is not implemented"); + } + + /** + * Returns a new Task that will be completed with the result of applying the specified SuccessContinuation to this Task when this Task completes successfully. If the previous Task fails, the onSuccessTask completion will be skipped and failure listeners will be invoked. + *

+ * If the previous Task is canceled, the returned Task will also be canceled and the SuccessContinuation would not execute. + * + * @param executor the executor to use to call the SuccessContinuation + * @see SuccessContinuation#then + */ + public Task onSuccessTask(Executor executor, SuccessContinuation successContinuation) { + throw new UnsupportedOperationException("onSuccessTask is not implemented"); + } + } diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskCompletionSource.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskCompletionSource.java index 32def519..00c4a972 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskCompletionSource.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskCompletionSource.java @@ -1,22 +1,15 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; import org.microg.gms.common.PublicApi; +import org.microg.gms.tasks.TaskImpl; /** * Provides the ability to create an incomplete {@link Task} and later complete it by either @@ -24,29 +17,78 @@ import org.microg.gms.common.PublicApi; */ @PublicApi public class TaskCompletionSource { + private TaskImpl task = new TaskImpl<>(); + + /** + * Creates an instance of {@link TaskCompletionSource}. + */ public TaskCompletionSource() { } + /** + * Creates an instance of {@link TaskCompletionSource} with a {@link CancellationToken} so that the Task can be set to canceled when {@link CancellationToken} is canceled. + */ + public TaskCompletionSource(CancellationToken token) { + token.onCanceledRequested(() -> { + try { + task.cancel(); + } catch (DuplicateTaskCompletionException ignored) { + } + }); + } + /** * Returns the Task. */ public Task getTask() { - return null; + return task; } /** * Completes the Task with the specified exception. + * * @throws IllegalStateException if the Task is already complete */ public void setException(Exception e) { + task.setException(e); + } + /** + * Completes the Task with the specified exception, unless the Task has already completed. + * If the Task has already completed, the call does nothing. + * + * @return {@code true} if the exception was set successfully, {@code false} otherwise + */ + public boolean trySetException(Exception e) { + try { + setException(e); + return true; + } catch (DuplicateTaskCompletionException ignored) { + return false; + } } /** * Completes the Task with the specified result. + * * @throws IllegalStateException if the Task is already complete */ public void setResult(TResult result) { + task.setResult(result); + } + /** + * Completes the Task with the specified result, unless the Task has already completed. + * If the Task has already completed, the call does nothing. + * + * @return {@code true} if the result was set successfully, {@code false} otherwise + */ + public boolean trySetResult(TResult result) { + try { + setResult(result); + return true; + } catch (DuplicateTaskCompletionException ignored) { + return false; + } } } diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskExecutors.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskExecutors.java new file mode 100644 index 00000000..c4947e13 --- /dev/null +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/TaskExecutors.java @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; + +import android.os.Handler; +import android.os.Looper; + +import org.microg.gms.common.PublicApi; + +import java.util.concurrent.Executor; + +/** + * Standard {@link Executor} instances for use with {@link Task}. + */ +@PublicApi +public final class TaskExecutors { + /** + * An Executor that uses the main application thread. + */ + public static final Executor MAIN_THREAD = new Executor() { + private Handler handler = new Handler(Looper.getMainLooper()); + @Override + public void execute(Runnable command) { + handler.post(command); + } + }; +} diff --git a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java index 41f31c7b..43452562 100644 --- a/play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java +++ b/play-services-tasks/src/main/java/com/google/android/gms/tasks/Tasks.java @@ -1,17 +1,9 @@ /* - * Copyright (C) 2013-2017 microG Project Team - * - * 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. + * SPDX-FileCopyrightText: 2016, microG Project Team + * SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.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.tasks; diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/CancellationTokenImpl.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/CancellationTokenImpl.java new file mode 100644 index 00000000..b2a69096 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/CancellationTokenImpl.java @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.CancellationToken; +import com.google.android.gms.tasks.DuplicateTaskCompletionException; +import com.google.android.gms.tasks.OnTokenCanceledListener; + +public class CancellationTokenImpl extends CancellationToken { + private TaskImpl task = new TaskImpl<>(); + + @Override + public boolean isCancellationRequested() { + return task.isComplete(); + } + + @Override + public CancellationToken onCanceledRequested(OnTokenCanceledListener listener) { + task.addOnSuccessListener(aVoid -> listener.onCanceled()); + return this; + } + + public void cancel() { + try { + task.cancel(); + } catch (DuplicateTaskCompletionException ignored) { + } + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/CancelledExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/CancelledExecutor.java new file mode 100644 index 00000000..6b495749 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/CancelledExecutor.java @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.OnCanceledListener; +import com.google.android.gms.tasks.Task; + +import java.util.concurrent.Executor; + +public class CancelledExecutor extends UpdateExecutor { + private OnCanceledListener listener; + + public CancelledExecutor(Executor executor, OnCanceledListener listener) { + super(executor); + this.listener = listener; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isCanceled()) { + execute(() -> listener.onCanceled()); + } + } + + @Override + public void cancel() { + super.cancel(); + listener = null; + } +} + diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/CompletedExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/CompletedExecutor.java new file mode 100644 index 00000000..18267d7f --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/CompletedExecutor.java @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; + +import java.util.concurrent.Executor; + +public class CompletedExecutor extends UpdateExecutor { + private OnCompleteListener listener; + + public CompletedExecutor(Executor executor, OnCompleteListener listener) { + super(executor); + this.listener = listener; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isComplete()) { + execute(() -> listener.onComplete(task)); + } + } + + @Override + public void cancel() { + super.cancel(); + listener = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationExecutor.java new file mode 100644 index 00000000..33606df3 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationExecutor.java @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.Continuation; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; + +import java.util.concurrent.Executor; + +public class ContinuationExecutor extends UpdateExecutor { + private Continuation continuation; + private TaskCompletionSource completionSource = new TaskCompletionSource<>(); + + public ContinuationExecutor(Executor executor, Continuation continuation) { + super(executor); + this.continuation = continuation; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isComplete()) { + execute(() -> { + try { + completionSource.setResult(continuation.then(task)); + } catch (Exception e) { + completionSource.setException(e); + } + }); + } + } + + public Task getTask() { + return completionSource.getTask(); + } + + @Override + public void cancel() { + super.cancel(); + continuation = null; + completionSource = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationWithExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationWithExecutor.java new file mode 100644 index 00000000..6ec69b0d --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/ContinuationWithExecutor.java @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.Continuation; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; + +import java.util.concurrent.Executor; + +public class ContinuationWithExecutor extends UpdateExecutor { + private Continuation> continuation; + private TaskCompletionSource completionSource = new TaskCompletionSource<>(); + + public ContinuationWithExecutor(Executor executor, Continuation> continuation) { + super(executor); + this.continuation = continuation; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isComplete()) { + execute(() -> { + try { + continuation.then(task).addOnCompleteListener(this, (subTask) -> { + if (subTask.isSuccessful()) { + completionSource.setResult(subTask.getResult()); + } else { + completionSource.setException(subTask.getException()); + } + }); + } catch (Exception e) { + completionSource.setException(e); + } + }); + } + } + + public Task getTask() { + return completionSource.getTask(); + } + + @Override + public void cancel() { + super.cancel(); + continuation = null; + completionSource = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/FailureExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/FailureExecutor.java new file mode 100644 index 00000000..3a670337 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/FailureExecutor.java @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.Task; + +import java.util.concurrent.Executor; + +public class FailureExecutor extends UpdateExecutor { + private OnFailureListener listener; + + public FailureExecutor(Executor executor, OnFailureListener listener) { + super(executor); + this.listener = listener; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isComplete() && !task.isSuccessful() && !task.isCanceled()) { + execute(() -> listener.onFailure(task.getException())); + } + } + + @Override + public void cancel() { + super.cancel(); + listener = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessContinuationExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessContinuationExecutor.java new file mode 100644 index 00000000..963ae64f --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessContinuationExecutor.java @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.SuccessContinuation; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.TaskCompletionSource; + +import java.util.concurrent.Executor; + +public class SuccessContinuationExecutor extends UpdateExecutor { + private SuccessContinuation continuation; + private TaskCompletionSource completionSource = new TaskCompletionSource<>(); + + public SuccessContinuationExecutor(Executor executor, SuccessContinuation continuation) { + super(executor); + this.continuation = continuation; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isSuccessful()) { + execute(() -> { + try { + continuation.then(task.getResult()).addOnCompleteListener(this, (subTask) -> { + if (subTask.isSuccessful()) { + completionSource.setResult(subTask.getResult()); + } else { + completionSource.setException(subTask.getException()); + } + }); + } catch (Exception e) { + completionSource.setException(e); + } + }); + } else { + completionSource.setException(task.getException()); + } + } + + public Task getTask() { + return completionSource.getTask(); + } + + @Override + public void cancel() { + super.cancel(); + continuation = null; + completionSource = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessExecutor.java new file mode 100644 index 00000000..da6816d0 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/SuccessExecutor.java @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; + +import java.util.concurrent.Executor; + +public class SuccessExecutor extends UpdateExecutor { + private OnSuccessListener listener; + + public SuccessExecutor(Executor executor, OnSuccessListener listener) { + super(executor); + this.listener = listener; + } + + @Override + public void onTaskUpdate(Task task) { + if (task.isSuccessful()) { + execute(() -> listener.onSuccess(task.getResult())); + } + } + + @Override + public void cancel() { + super.cancel(); + listener = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java new file mode 100644 index 00000000..ae5c42f1 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/TaskImpl.java @@ -0,0 +1,240 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import android.app.Activity; + +import com.google.android.gms.tasks.Continuation; +import com.google.android.gms.tasks.DuplicateTaskCompletionException; +import com.google.android.gms.tasks.OnCanceledListener; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.RuntimeExecutionException; +import com.google.android.gms.tasks.SuccessContinuation; +import com.google.android.gms.tasks.Task; + +import java.util.Queue; +import java.util.concurrent.CancellationException; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; + +import static com.google.android.gms.tasks.TaskExecutors.MAIN_THREAD; + +public class TaskImpl extends Task { + private final Object lock = new Object(); + private boolean completed; + private boolean cancelled; + private TResult result; + private Exception exception; + private Queue> completionQueue = new LinkedBlockingQueue<>(); + + @Override + public Task addOnCanceledListener(OnCanceledListener listener) { + return addOnCanceledListener(MAIN_THREAD, listener); + } + + @Override + public Task addOnCanceledListener(Executor executor, OnCanceledListener listener) { + return enqueueOrInvoke(new CancelledExecutor<>(executor, listener)); + } + + @Override + public Task addOnCanceledListener(Activity activity, OnCanceledListener listener) { + return enqueueOrInvoke(activity, new CancelledExecutor<>(MAIN_THREAD, listener)); + } + + @Override + public Task addOnCompleteListener(OnCompleteListener listener) { + return addOnCompleteListener(MAIN_THREAD, listener); + } + + @Override + public Task addOnCompleteListener(Executor executor, OnCompleteListener listener) { + return enqueueOrInvoke(new CompletedExecutor<>(executor, listener)); + } + + @Override + public Task addOnCompleteListener(Activity activity, OnCompleteListener listener) { + return enqueueOrInvoke(activity, new CompletedExecutor<>(MAIN_THREAD, listener)); + } + + @Override + public Task addOnFailureListener(OnFailureListener listener) { + return addOnFailureListener(MAIN_THREAD, listener); + } + + @Override + public Task addOnFailureListener(Executor executor, OnFailureListener listener) { + return enqueueOrInvoke(new FailureExecutor<>(executor, listener)); + } + + @Override + public Task addOnFailureListener(Activity activity, OnFailureListener listener) { + return enqueueOrInvoke(activity, new FailureExecutor<>(MAIN_THREAD, listener)); + } + + @Override + public Task addOnSuccessListener(OnSuccessListener listener) { + return addOnSuccessListener(MAIN_THREAD, listener); + } + + @Override + public Task addOnSuccessListener(Executor executor, OnSuccessListener listener) { + return enqueueOrInvoke(new SuccessExecutor<>(executor, listener)); + } + + @Override + public Task addOnSuccessListener(Activity activity, OnSuccessListener listener) { + return enqueueOrInvoke(activity, new SuccessExecutor<>(MAIN_THREAD, listener)); + } + + @Override + public Task continueWith(Continuation continuation) { + return continueWith(MAIN_THREAD, continuation); + } + + @Override + public Task continueWith(Executor executor, Continuation continuation) { + ContinuationExecutor c = new ContinuationExecutor<>(executor, continuation); + enqueueOrInvoke(c); + return c.getTask(); + } + + @Override + public Task continueWithTask(Continuation> continuation) { + return continueWithTask(MAIN_THREAD, continuation); + } + + @Override + public Task continueWithTask(Executor executor, Continuation> continuation) { + ContinuationWithExecutor c = new ContinuationWithExecutor<>(executor, continuation); + enqueueOrInvoke(c); + return c.getTask(); + } + + @Override + public Exception getException() { + synchronized (lock) { + return exception; + } + } + + @Override + public TResult getResult() { + synchronized (lock) { + if (!completed) throw new IllegalStateException("Task is not yet complete"); + if (cancelled) throw new CancellationException("Task is canceled"); + if (exception != null) throw new RuntimeExecutionException(exception); + return result; + } + } + + @Override + public TResult getResult(Class exceptionType) throws X { + synchronized (lock) { + if (!completed) throw new IllegalStateException("Task is not yet complete"); + if (cancelled) throw new CancellationException("Task is canceled"); + if (exceptionType.isInstance(exception)) throw exceptionType.cast(exception); + if (exception != null) throw new RuntimeExecutionException(exception); + return result; + } + } + + @Override + public boolean isCanceled() { + synchronized (lock) { + return cancelled; + } + } + + @Override + public boolean isComplete() { + synchronized (lock) { + return completed; + } + } + + @Override + public boolean isSuccessful() { + synchronized (lock) { + return completed && !cancelled && exception == null; + } + } + + private void registerActivityStop(Activity activity, UpdateListener listener) { + UpdateListenerLifecycleObserver.getObserverForActivity(activity).registerActivityStopListener(listener); + } + + private Task enqueueOrInvoke(Activity activity, UpdateListener listener) { + synchronized (lock) { + if (completed) { + listener.onTaskUpdate(this); + } else { + completionQueue.offer(listener); + registerActivityStop(activity, listener); + } + } + return this; + } + + private Task enqueueOrInvoke(UpdateListener listener) { + synchronized (lock) { + if (completed) { + listener.onTaskUpdate(this); + } else { + completionQueue.offer(listener); + } + } + return this; + } + + private void notifyQueue() { + UpdateListener listener; + while ((listener = completionQueue.poll()) != null) { + listener.onTaskUpdate(this); + } + } + + public void cancel() { + synchronized (lock) { + if (completed) throw DuplicateTaskCompletionException.of(this); + this.completed = true; + this.cancelled = true; + notifyQueue(); + } + } + + public void setResult(TResult result) { + synchronized (lock) { + if (completed) throw DuplicateTaskCompletionException.of(this); + this.completed = true; + this.result = result; + notifyQueue(); + } + } + + public void setException(Exception exception) { + synchronized (lock) { + if (completed) throw DuplicateTaskCompletionException.of(this); + this.completed = true; + this.exception = exception; + notifyQueue(); + } + } + + @Override + public Task onSuccessTask(SuccessContinuation successContinuation) { + return onSuccessTask(MAIN_THREAD, successContinuation); + } + + @Override + public Task onSuccessTask(Executor executor, SuccessContinuation successContinuation) { + SuccessContinuationExecutor c = new SuccessContinuationExecutor<>(executor, successContinuation); + enqueueOrInvoke(c); + return c.getTask(); + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateExecutor.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateExecutor.java new file mode 100644 index 00000000..6c448646 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateExecutor.java @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import java.util.concurrent.Executor; + +public abstract class UpdateExecutor implements UpdateListener, Executor { + private Executor executor; + + public UpdateExecutor(Executor executor) { + this.executor = executor; + } + + @Override + public void execute(Runnable runnable) { + if (executor == null) return; + executor.execute(runnable); + } + + @Override + public void cancel() { + executor = null; + } +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListener.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListener.java new file mode 100644 index 00000000..d28c265a --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListener.java @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import com.google.android.gms.tasks.Task; + +public interface UpdateListener { + void onTaskUpdate(Task task); + + void cancel(); +} diff --git a/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListenerLifecycleObserver.java b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListenerLifecycleObserver.java new file mode 100644 index 00000000..dd307c50 --- /dev/null +++ b/play-services-tasks/src/main/java/org/microg/gms/tasks/UpdateListenerLifecycleObserver.java @@ -0,0 +1,98 @@ +/* + * SPDX-FileCopyrightText: 2020, microG Project Team + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.microg.gms.tasks; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.WeakHashMap; + +public class UpdateListenerLifecycleObserver { + private static WeakHashMap> map = new WeakHashMap<>(); + private static boolean activityLifecycleCallbacksRegistered = false; + private List>> list = new ArrayList<>(); + + public synchronized static UpdateListenerLifecycleObserver getObserverForActivity(Activity activity) { + WeakReference ref = map.get(activity); + if (ref != null) { + UpdateListenerLifecycleObserver observer = ref.get(); + if (observer != null) { + return observer; + } + } + + if (!activityLifecycleCallbacksRegistered) { + activity.getApplication().registerActivityLifecycleCallbacks(new MyActivityLifecycleCallbacks()); + activityLifecycleCallbacksRegistered = true; + } + + UpdateListenerLifecycleObserver newInstance = new UpdateListenerLifecycleObserver(); + map.put(activity, new WeakReference<>(newInstance)); + return newInstance; + } + + private UpdateListenerLifecycleObserver() { + } + + public synchronized void registerActivityStopListener(UpdateListener listener) { + list.add(new WeakReference<>(listener)); + } + + public synchronized void onStop() { + for (WeakReference> ref : list) { + UpdateListener listener = ref.get(); + listener.cancel(); + } + list.clear(); + } + + private static class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + + } + + @Override + public void onActivityStarted(Activity activity) { + + } + + @Override + public void onActivityResumed(Activity activity) { + + } + + @Override + public void onActivityPaused(Activity activity) { + + } + + @Override + public void onActivityStopped(Activity activity) { + WeakReference ref = map.get(activity); + if (ref != null) { + UpdateListenerLifecycleObserver observer = ref.get(); + if (observer != null) { + observer.onStop(); + } + } + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + + } + + @Override + public void onActivityDestroyed(Activity activity) { + + } + } +} diff --git a/play-services-wearable/src/main/java/com/google/android/gms/wearable/Wearable.java b/play-services-wearable/src/main/java/com/google/android/gms/wearable/Wearable.java new file mode 100644 index 00000000..e1fcd8ec --- /dev/null +++ b/play-services-wearable/src/main/java/com/google/android/gms/wearable/Wearable.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013-2017 microG Project Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.gms.wearable; + +import com.google.android.gms.common.api.Api; +import com.google.android.gms.common.api.GoogleApiClient; + +import org.microg.gms.common.PublicApi; +import org.microg.gms.wearable.DataApiImpl; +import org.microg.gms.wearable.MessageApiImpl; +import org.microg.gms.wearable.NodeApiImpl; +import org.microg.gms.wearable.WearableApiClientBuilder; + +/** + * An API for the Android Wear platform. + */ +@PublicApi +public class Wearable { + /** + * Token to pass to {@link GoogleApiClient.Builder#addApi(Api)} to enable the Wearable features. + */ + public static final Api API = new Api(new WearableApiClientBuilder()); + + public static final DataApi DataApi = new DataApiImpl(); + public static final MessageApi MessageApi = new MessageApiImpl(); + public static final NodeApi NodeApi = new NodeApiImpl(); + + public static class WearableOptions implements Api.ApiOptions.Optional { + /** + * Special option for microG to allow implementation of a FOSS first party Android Wear app + */ + @PublicApi(exclude = true) + public boolean firstPartyMode = false; + + public static class Builder { + public WearableOptions build() { + return new WearableOptions(); + } + } + } +}