Skip to content

Commit 72d0d25

Browse files
authored
Merge branch 'master' into mlStorage
2 parents 3b704d8 + 6759dd2 commit 72d0d25

File tree

9 files changed

+359
-5
lines changed

9 files changed

+359
-5
lines changed

firebase-installations/ktx/src/test/kotlin/com/google/firebase/installations/ktx/InstallationsTests.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ abstract class BaseTestCase {
6464
}
6565

6666
@RunWith(RobolectricTestRunner::class)
67-
class FunctionsTests : BaseTestCase() {
67+
class InstallationsTests : BaseTestCase() {
6868
@Test
69-
fun `installations should delegate to FirebaseFunctions#getInstance()`() {
69+
fun `installations should delegate to FirebaseInstallations#getInstance()`() {
7070
Truth.assertThat(Firebase.installations).isSameInstanceAs(FirebaseInstallations.getInstance())
7171
}
7272

7373
@Test
74-
fun `functions(app) should delegate to FirebaseFunctions#getInstance(FirebaseApp)`() {
74+
fun `installations(app) should delegate to FirebaseInstallations#getInstance(FirebaseApp)`() {
7575
val app = Firebase.app(EXISTING_APP)
7676
Truth.assertThat(Firebase.installations(app)).isSameInstanceAs(FirebaseInstallations.getInstance(app))
7777
}

firebase-ml-modeldownloader/api.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
11
// Signature format: 2.0
22
package com.google.firebase.ml.modeldownloader {
33

4-
public final class CustomModel {
4+
public class CustomModel {
55
method public long getDownloadId();
66
method @Nullable public java.io.File getFile();
77
method @NonNull public String getModelHash();
88
method @NonNull public String getName();
99
method public long getSize();
1010
}
1111

12+
public class CustomModelDownloadConditions {
13+
method public boolean isChargingRequired();
14+
method public boolean isDeviceIdleRequired();
15+
method public boolean isWifiRequired();
16+
}
17+
18+
public static class CustomModelDownloadConditions.Builder {
19+
ctor public CustomModelDownloadConditions.Builder();
20+
method @NonNull public com.google.firebase.ml.modeldownloader.CustomModelDownloadConditions build();
21+
method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.N) public com.google.firebase.ml.modeldownloader.CustomModelDownloadConditions.Builder requireCharging();
22+
method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.N) public com.google.firebase.ml.modeldownloader.CustomModelDownloadConditions.Builder requireDeviceIdle();
23+
method @NonNull public com.google.firebase.ml.modeldownloader.CustomModelDownloadConditions.Builder requireWifi();
24+
}
25+
26+
public enum DownloadType {
27+
enum_constant public static final com.google.firebase.ml.modeldownloader.DownloadType LATEST_MODEL;
28+
enum_constant public static final com.google.firebase.ml.modeldownloader.DownloadType LOCAL_MODEL;
29+
enum_constant public static final com.google.firebase.ml.modeldownloader.DownloadType LOCAL_MODEL_UPDATE_IN_BACKGROUND;
30+
}
31+
1232
public class FirebaseModelDownloader {
33+
method @NonNull public com.google.android.gms.tasks.Task<java.lang.Void> deleteDownloadedModel(@NonNull String);
1334
method @NonNull public static com.google.firebase.ml.modeldownloader.FirebaseModelDownloader getInstance();
1435
method @NonNull public static com.google.firebase.ml.modeldownloader.FirebaseModelDownloader getInstance(@NonNull com.google.firebase.FirebaseApp);
36+
method @NonNull public com.google.android.gms.tasks.Task<com.google.firebase.ml.modeldownloader.CustomModel> getModel(@NonNull String, @NonNull com.google.firebase.ml.modeldownloader.DownloadType, @Nullable com.google.firebase.ml.modeldownloader.CustomModelDownloadConditions);
37+
method @NonNull public com.google.android.gms.tasks.Task<java.util.Set<com.google.firebase.ml.modeldownloader.CustomModel>> listDownloadedModels();
1538
}
1639

1740
}

firebase-ml-modeldownloader/firebase-ml-modeldownloader.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ dependencies {
5353
annotationProcessor "com.google.auto.value:auto-value:1.6.5"
5454

5555
testImplementation 'androidx.test:core:1.3.0'
56+
testImplementation 'com.google.truth:truth:1.0.1'
5657
testImplementation 'junit:junit:4.13'
5758
testImplementation "org.robolectric:robolectric:$robolectricVersion"
5859
}

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/CustomModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
* on a device. The model file associated with this model can be updated, once the new model file is
2525
* fully uploaded, the original model file will be removed as soon as it is safe to do so.
2626
*/
27-
public final class CustomModel {
2827

28+
public class CustomModel {
2929
private final String name;
3030
private final long downloadId;
3131
private final long fileSize;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.ml.modeldownloader;
16+
17+
import android.annotation.TargetApi;
18+
import android.os.Build.VERSION_CODES;
19+
import androidx.annotation.NonNull;
20+
import androidx.annotation.RequiresApi;
21+
import com.google.android.gms.common.internal.Objects;
22+
23+
/** Conditions to allow download of custom models. */
24+
public class CustomModelDownloadConditions {
25+
private final boolean isChargingRequired;
26+
private final boolean isWifiRequired;
27+
private final boolean isDeviceIdleRequired;
28+
29+
private CustomModelDownloadConditions(
30+
boolean isChargingRequired, boolean isWifiRequired, boolean isDeviceIdleRequired) {
31+
this.isChargingRequired = isChargingRequired;
32+
this.isWifiRequired = isWifiRequired;
33+
this.isDeviceIdleRequired = isDeviceIdleRequired;
34+
}
35+
36+
/** @return true if charging is required for download. */
37+
public boolean isChargingRequired() {
38+
return isChargingRequired;
39+
}
40+
41+
/** @return true if wifi is required for download. */
42+
public boolean isWifiRequired() {
43+
return isWifiRequired;
44+
}
45+
46+
/** @return true if device idle is required for download. */
47+
public boolean isDeviceIdleRequired() {
48+
return isDeviceIdleRequired;
49+
}
50+
51+
/** Builder of {@link CustomModelDownloadConditions}. */
52+
public static class Builder {
53+
private boolean isChargingRequired = false;
54+
private boolean isWifiRequired = false;
55+
private boolean isDeviceIdleRequired = false;
56+
57+
/** Sets whether charging is required. Only works on Android N and above. */
58+
@NonNull
59+
@RequiresApi(VERSION_CODES.N)
60+
@TargetApi(VERSION_CODES.N)
61+
public Builder requireCharging() {
62+
this.isChargingRequired = true;
63+
return this;
64+
}
65+
66+
/** Sets whether wifi is required. */
67+
@NonNull
68+
public Builder requireWifi() {
69+
this.isWifiRequired = true;
70+
return this;
71+
}
72+
73+
/**
74+
* Sets whether device idle is required.
75+
*
76+
* <p>Idle mode is a loose definition provided by the system, which means that the device is not
77+
* in use, and has not been in use for some time.
78+
*
79+
* <p>Only works on Android N and above.
80+
*/
81+
@NonNull
82+
@RequiresApi(VERSION_CODES.N)
83+
@TargetApi(VERSION_CODES.N)
84+
public Builder requireDeviceIdle() {
85+
this.isDeviceIdleRequired = true;
86+
return this;
87+
}
88+
89+
/** Builds {@link CustomModelDownloadConditions}. */
90+
@NonNull
91+
public CustomModelDownloadConditions build() {
92+
return new CustomModelDownloadConditions(
93+
isChargingRequired, isWifiRequired, isDeviceIdleRequired);
94+
}
95+
}
96+
97+
@Override
98+
public boolean equals(Object o) {
99+
if (o == this) {
100+
return true;
101+
}
102+
103+
if (!(o instanceof CustomModelDownloadConditions)) {
104+
return false;
105+
}
106+
107+
CustomModelDownloadConditions other = (CustomModelDownloadConditions) o;
108+
return isChargingRequired == other.isChargingRequired
109+
&& isDeviceIdleRequired == other.isDeviceIdleRequired
110+
&& isWifiRequired == other.isWifiRequired;
111+
}
112+
113+
@Override
114+
public int hashCode() {
115+
return Objects.hashCode(isChargingRequired, isWifiRequired, isDeviceIdleRequired);
116+
}
117+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.ml.modeldownloader;
16+
17+
public enum DownloadType {
18+
/** Use local model when present, otherwise download and return latest model */
19+
LOCAL_MODEL,
20+
/**
21+
* When local model present: Use local model and download latest model in background. Otherwise,
22+
* download and return latest model.
23+
*/
24+
LOCAL_MODEL_UPDATE_IN_BACKGROUND,
25+
/**
26+
* Always return latest model, check for latest model and download new model (when needed) before
27+
* returning.
28+
*/
29+
LATEST_MODEL
30+
}

firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@
1616
import androidx.annotation.NonNull;
1717
import androidx.annotation.VisibleForTesting;
1818
import com.google.android.gms.common.internal.Preconditions;
19+
import com.google.android.gms.tasks.Task;
1920
import com.google.firebase.FirebaseApp;
2021
import com.google.firebase.FirebaseOptions;
22+
import androidx.annotation.Nullable;
23+
import java.util.Set;
2124

2225
public class FirebaseModelDownloader {
2326

@@ -50,6 +53,49 @@ public static FirebaseModelDownloader getInstance(@NonNull FirebaseApp app) {
5053
return app.get(FirebaseModelDownloader.class);
5154
}
5255

56+
/**
57+
* Get the downloaded model file based on download type and conditions. DownloadType behaviours:
58+
*
59+
* <ul>
60+
* <li>{@link DownloadType#LOCAL_MODEL}: returns the current model if present, otherwise
61+
* triggers new download (or finds one in progress) and only completes when download is
62+
* finished
63+
* <li>{@link DownloadType#LOCAL_MODEL_UPDATE_IN_BACKGROUND}: returns the current model if
64+
* present and triggers an update to fetch a new version in the background. If no local
65+
* model is present triggers a new download (or finds one in progress) and only completes
66+
* when download is finished.
67+
* <li>{@link DownloadType#LATEST_MODEL}: check for latest model, if different from local model,
68+
* trigger new download, task only completes when download finishes
69+
* </ul>
70+
*
71+
* @param modelName - model name
72+
* @param downloadType - download type
73+
* @param conditions - download conditions
74+
* @return Custom model
75+
*/
76+
@NonNull
77+
public Task<CustomModel> getModel(
78+
@NonNull String modelName,
79+
@NonNull DownloadType downloadType,
80+
@Nullable CustomModelDownloadConditions conditions) {
81+
throw new UnsupportedOperationException("Not yet implemented.");
82+
}
83+
84+
/** @return The set of all models that are downloaded to this device. */
85+
@NonNull
86+
public Task<Set<CustomModel>> listDownloadedModels() {
87+
throw new UnsupportedOperationException("Not yet implemented.");
88+
}
89+
90+
/*
91+
* Delete old local models, when no longer in use.
92+
* @param modelName - name of the model
93+
*/
94+
@NonNull
95+
public Task<Void> deleteDownloadedModel(@NonNull String modelName) {
96+
throw new UnsupportedOperationException("Not yet implemented.");
97+
}
98+
5399
/** Returns the nick name of the {@link FirebaseApp} of this {@link FirebaseModelDownloader} */
54100
@VisibleForTesting
55101
String getApplicationId() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.ml.modeldownloader;
16+
17+
import static com.google.common.truth.Truth.assertThat;
18+
19+
import org.junit.Test;
20+
import org.junit.runner.RunWith;
21+
import org.robolectric.RobolectricTestRunner;
22+
23+
/** Tests of {@link CustomModelDownloadConditions} */
24+
@RunWith(RobolectricTestRunner.class)
25+
public class CustomModelDownloadConditionsTest {
26+
27+
@Test
28+
public void testDefaultBuilder() {
29+
CustomModelDownloadConditions conditions = new CustomModelDownloadConditions.Builder().build();
30+
assertThat(conditions.isChargingRequired()).isFalse();
31+
assertThat(conditions.isWifiRequired()).isFalse();
32+
assertThat(conditions.isDeviceIdleRequired()).isFalse();
33+
}
34+
35+
@Test
36+
public void testConfigConditions() {
37+
CustomModelDownloadConditions conditions =
38+
new CustomModelDownloadConditions.Builder().requireCharging().requireWifi().build();
39+
assertThat(conditions.isChargingRequired()).isTrue();
40+
assertThat(conditions.isWifiRequired()).isTrue();
41+
assertThat(conditions.isDeviceIdleRequired()).isFalse();
42+
}
43+
44+
@Test
45+
public void testTwoDefaultConditionsSame() {
46+
CustomModelDownloadConditions conditions1 = new CustomModelDownloadConditions.Builder().build();
47+
CustomModelDownloadConditions conditions2 = new CustomModelDownloadConditions.Builder().build();
48+
assertThat(conditions1).isEqualTo(conditions2);
49+
}
50+
51+
@Test
52+
public void testTwoConfigedConditionsSame() {
53+
CustomModelDownloadConditions conditions1 =
54+
new CustomModelDownloadConditions.Builder().requireDeviceIdle().requireCharging().build();
55+
CustomModelDownloadConditions conditions2 =
56+
new CustomModelDownloadConditions.Builder().requireCharging().requireDeviceIdle().build();
57+
assertThat(conditions1).isEqualTo(conditions2);
58+
}
59+
60+
@Test
61+
public void testTwoConfigedConditionsDifferent() {
62+
CustomModelDownloadConditions conditions1 =
63+
new CustomModelDownloadConditions.Builder().requireCharging().build();
64+
CustomModelDownloadConditions conditions2 =
65+
new CustomModelDownloadConditions.Builder().requireCharging().requireDeviceIdle().build();
66+
assertThat(conditions1).isNotEqualTo(conditions2);
67+
}
68+
}

0 commit comments

Comments
 (0)