Skip to content

Commit d5fe93a

Browse files
naznia-devcopybara-github
authored andcommitted
Initial release of the Key Attestation Verifier app.
Key changes include: - Relocating all source files and resources. - Updating the package name to com.android.attestation.app. - Generalizing UI strings and colors. - Moving the "Attest Device IDs" toggle to the main activity layout. - Adding BUILD targets for the Android library and binary. PiperOrigin-RevId: 893416680
1 parent b1bf437 commit d5fe93a

16 files changed

Lines changed: 1790 additions & 0 deletions
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.android.attestation.app">
4+
5+
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33"/>
6+
<application
7+
android:allowBackup="true"
8+
android:label="@string/app_name"
9+
android:supportsRtl="true"
10+
android:theme="@style/AppTheme"
11+
android:icon="@drawable/ic_launcher_verifier"
12+
android:roundIcon="@drawable/ic_launcher_verifier">
13+
14+
<activity android:name=".MainActivity" android:exported="true">
15+
<intent-filter>
16+
<action android:name="android.intent.action.MAIN" />
17+
<category android:name="android.intent.category.LAUNCHER" />
18+
</intent-filter>
19+
</activity>
20+
</application>
21+
</manifest>

java/com/android/attestation/app/AttestationUiManager.java

Lines changed: 452 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.android.attestation.app;
17+
18+
import android.app.Activity;
19+
import android.content.Context;
20+
import android.net.ConnectivityManager;
21+
import android.net.Network;
22+
import android.net.NetworkCapabilities;
23+
import android.security.KeyStoreException;
24+
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
25+
import java.net.ConnectException;
26+
import java.net.SocketTimeoutException;
27+
import java.net.UnknownHostException;
28+
29+
/**
30+
* Utility class providing helper methods to verify Android device states, build configurations, and
31+
* user profile environments.
32+
*/
33+
public final class AttestationUtils {
34+
35+
public static void showAlertDialog(
36+
Activity activity, String title, String message, String buttonText) {
37+
new MaterialAlertDialogBuilder(activity)
38+
.setTitle(title)
39+
.setMessage(message)
40+
.setPositiveButton(buttonText, null)
41+
.setCancelable(false)
42+
.show();
43+
}
44+
45+
/**
46+
* Returns {@code true} if the network is likely available, or if its status cannot be determined.
47+
*
48+
* <p>This method fails open: it returns {@code false} only when it's definitively known that the
49+
* network is unavailable. If there's insufficient information or an exception occurs during the
50+
* check, it defaults to returning {@code true}.
51+
*/
52+
public static boolean isNetworkAvailable(Context context) {
53+
try {
54+
ConnectivityManager cm =
55+
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
56+
57+
if (cm == null) {
58+
return true;
59+
}
60+
61+
Network activeNetwork = cm.getActiveNetwork();
62+
if (activeNetwork == null) {
63+
return false;
64+
}
65+
66+
NetworkCapabilities capabilities = cm.getNetworkCapabilities(activeNetwork);
67+
return capabilities == null
68+
|| capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
69+
70+
} catch (RuntimeException e) {
71+
return true;
72+
}
73+
}
74+
75+
public static boolean isCannotAttestIdsError(Exception e) {
76+
int errorCode = getKeystoreErrorCode(e);
77+
78+
return errorCode == KeyStoreException.ERROR_ID_ATTESTATION_FAILURE;
79+
}
80+
81+
public static boolean isNetworkError(Exception e) {
82+
int errorCode = getKeystoreErrorCode(e);
83+
84+
return errorCode == KeyStoreException.RETRY_WHEN_CONNECTIVITY_AVAILABLE
85+
|| e instanceof UnknownHostException
86+
|| e instanceof SocketTimeoutException
87+
|| e instanceof ConnectException;
88+
}
89+
90+
private static int getKeystoreErrorCode(Exception e) {
91+
Throwable throwable = e instanceof KeyStoreException ? e : e.getCause();
92+
if (throwable instanceof KeyStoreException kse) {
93+
return kse.getNumericErrorCode();
94+
}
95+
return Integer.MAX_VALUE;
96+
}
97+
98+
private AttestationUtils() {}
99+
}

0 commit comments

Comments
 (0)