docs: Update prebuilts for nyc-dev samples

Synced to commits:
- //developers/samples/android
  fc1c2eac13aa87531f030f8c65d7e27c301135af
- //developers/build
  18730e97939c9545a26e52d135a99045c86abeaf

Change-Id: I88952b8f86921739af9fed6b87d39a72af835748
This commit is contained in:
Trevor Johns
2016-08-11 15:54:50 -07:00
parent 1f1926963c
commit a374bcd44d
13 changed files with 164 additions and 73 deletions

View File

@@ -9,6 +9,6 @@ sample.group=Admin
enable or disable other apps and how to set restrictions to them. Intents can be enable or disable other apps and how to set restrictions to them. Intents can be
configured to be forwarded between primary account and managed profile. Finally, you can configured to be forwarded between primary account and managed profile. Finally, you can
wipe all the data associated with the profile. wipe all the data associated with the profile.
Note that there can only be one managed profile on a device. Note that there can only be one managed profile on a device.
</p> </p>

View File

@@ -25,7 +25,7 @@
enable or disable other apps and how to set restrictions to them. Intents can be enable or disable other apps and how to set restrictions to them. Intents can be
configured to be forwarded between primary account and managed profile. Finally, you can configured to be forwarded between primary account and managed profile. Finally, you can
wipe all the data associated with the profile. wipe all the data associated with the profile.
Note that there can only be one managed profile on a device. Note that there can only be one managed profile on a device.
]]> ]]>

View File

@@ -19,9 +19,6 @@
android:versionCode="1" android:versionCode="1"
android:versionName="1.0" > android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7"
android:targetSdkVersion="21" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"

View File

@@ -22,7 +22,7 @@
> >
<LinearLayout android:layout_width="match_parent" <LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin" android:paddingTop="@dimen/activity_vertical_margin"

View File

@@ -15,7 +15,6 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="title_activity_card_view">CardViewActivity</string>
<string name="cardview_contents">This is a CardView widget. CardView widgets can have <string name="cardview_contents">This is a CardView widget. CardView widgets can have
shadows and rounded corners. shadows and rounded corners.
\n\nTo create a card with a shadow, use the <font fgcolor="#FFFFFFFF">android:elevation</font> \n\nTo create a card with a shadow, use the <font fgcolor="#FFFFFFFF">android:elevation</font>

View File

@@ -57,6 +57,7 @@
android:duplicateParentState="true" android:duplicateParentState="true"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="16dp" /> android:layout_marginLeft="16dp"
android:layout_marginStart="16dp" />
</com.example.android.customchoicelist.CheckableLinearLayout> </com.example.android.customchoicelist.CheckableLinearLayout>

View File

@@ -15,6 +15,8 @@
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="HONEYCOMB"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"

View File

@@ -26,6 +26,8 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewOutlineProvider; import android.view.ViewOutlineProvider;
import java.util.Locale;
public class ElevationDragFragment extends Fragment { public class ElevationDragFragment extends Fragment {
public static final String TAG = "ElevationDragFragment"; public static final String TAG = "ElevationDragFragment";
@@ -84,7 +86,7 @@ public class ElevationDragFragment extends Fragment {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
mElevation += mElevationStep; mElevation += mElevationStep;
Log.d(TAG, String.format("Elevation: %.1f", mElevation)); Log.d(TAG, String.format(Locale.US, "Elevation: %.1f", mElevation));
floatingShape.setElevation(mElevation); floatingShape.setElevation(mElevation);
} }
}); });
@@ -98,7 +100,7 @@ public class ElevationDragFragment extends Fragment {
if (mElevation < 0) { if (mElevation < 0) {
mElevation = 0; mElevation = 0;
} }
Log.d(TAG, String.format("Elevation: %.1f", mElevation)); Log.d(TAG, String.format(Locale.US, "Elevation: %.1f", mElevation));
floatingShape.setElevation(mElevation); floatingShape.setElevation(mElevation);
} }
}); });

View File

@@ -77,8 +77,27 @@
android:layout_gravity="end" android:layout_gravity="end"
android:textColor="?android:attr/textColorPrimaryInverse" android:textColor="?android:attr/textColorPrimaryInverse"
android:text="@string/purchase" android:text="@string/purchase"
android:id="@+id/purchase_button" android:id="@+id/purchase_button" />
android:layout_alignParentEnd="true"/>
<Button style="@android:style/Widget.Material.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="4dp"
android:layout_gravity="end"
android:textColor="?android:attr/textColorPrimaryInverse"
android:text="@string/purchase_not_invalidated"
android:id="@+id/purchase_button_not_invalidated" />
<TextView
android:id="@+id/purchase_button_not_invalidated_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:gravity="end"
android:textAlignment="gravity"
android:text="@string/purchase_button_not_invalidated_description"
/>
<TextView <TextView
android:id="@+id/confirmation_message" android:id="@+id/confirmation_message"

View File

@@ -31,6 +31,10 @@
<string name="fingerprint_hint">Touch sensor</string> <string name="fingerprint_hint">Touch sensor</string>
<string name="password_description">Enter your store password to continue</string> <string name="password_description">Enter your store password to continue</string>
<string name="purchase">Purchase</string> <string name="purchase">Purchase</string>
<string name="purchase_not_invalidated">Purchase not invalidated</string>
<string name="purchase_button_not_invalidated_description">
You can proceed to purchase with this button \n even if a new fingerprint is enrolled
</string>
<string name="fingerprint_not_recognized">Fingerprint not recognized. Try again</string> <string name="fingerprint_not_recognized">Fingerprint not recognized. Try again</string>
<string name="fingerprint_success">Fingerprint recognized</string> <string name="fingerprint_success">Fingerprint recognized</string>
<string name="item_title">White Mesh Pluto Backpack</string> <string name="item_title">White Mesh Pluto Backpack</string>

View File

@@ -181,12 +181,12 @@ public class FingerprintAuthenticationDialogFragment extends DialogFragment
if (mUseFingerprintFutureCheckBox.isChecked()) { if (mUseFingerprintFutureCheckBox.isChecked()) {
// Re-create the key so that fingerprints including new ones are validated. // Re-create the key so that fingerprints including new ones are validated.
mActivity.createKey(); mActivity.createKey(MainActivity.DEFAULT_KEY_NAME, true);
mStage = Stage.FINGERPRINT; mStage = Stage.FINGERPRINT;
} }
} }
mPassword.setText(""); mPassword.setText("");
mActivity.onPurchased(false /* without Fingerprint */); mActivity.onPurchased(false /* without Fingerprint */, null);
dismiss(); dismiss();
} }
@@ -243,7 +243,7 @@ public class FingerprintAuthenticationDialogFragment extends DialogFragment
public void onAuthenticated() { public void onAuthenticated() {
// Callback from FingerprintUiHelper. Let the activity know that authentication was // Callback from FingerprintUiHelper. Let the activity know that authentication was
// successful. // successful.
mActivity.onPurchased(true /* withFingerprint */); mActivity.onPurchased(true /* withFingerprint */, mCryptoObject);
dismiss(); dismiss();
} }

View File

@@ -21,11 +21,13 @@ import android.app.KeyguardManager;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties; import android.security.keystore.KeyProperties;
import android.support.annotation.Nullable;
import android.util.Base64; import android.util.Base64;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
@@ -61,12 +63,11 @@ public class MainActivity extends Activity {
private static final String DIALOG_FRAGMENT_TAG = "myFragment"; private static final String DIALOG_FRAGMENT_TAG = "myFragment";
private static final String SECRET_MESSAGE = "Very secret message"; private static final String SECRET_MESSAGE = "Very secret message";
/** Alias for our key in the Android Key Store */ private static final String KEY_NAME_NOT_INVALIDATED = "key_not_invalidated";
private static final String KEY_NAME = "my_key"; static final String DEFAULT_KEY_NAME = "default_key";
private KeyStore mKeyStore; private KeyStore mKeyStore;
private KeyGenerator mKeyGenerator; private KeyGenerator mKeyGenerator;
private Cipher mCipher;
private SharedPreferences mSharedPreferences; private SharedPreferences mSharedPreferences;
@Override @Override
@@ -85,8 +86,13 @@ public class MainActivity extends Activity {
} catch (NoSuchAlgorithmException | NoSuchProviderException e) { } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("Failed to get an instance of KeyGenerator", e); throw new RuntimeException("Failed to get an instance of KeyGenerator", e);
} }
Cipher defaultCipher;
Cipher cipherNotInvalidated;
try { try {
mCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" defaultCipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
cipherNotInvalidated = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7); + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) { } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
@@ -97,6 +103,22 @@ public class MainActivity extends Activity {
KeyguardManager keyguardManager = getSystemService(KeyguardManager.class); KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class); FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
Button purchaseButton = (Button) findViewById(R.id.purchase_button); Button purchaseButton = (Button) findViewById(R.id.purchase_button);
Button purchaseButtonNotInvalidated = (Button) findViewById(
R.id.purchase_button_not_invalidated);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
purchaseButtonNotInvalidated.setEnabled(true);
purchaseButtonNotInvalidated.setOnClickListener(
new PurchaseButtonClickListener(cipherNotInvalidated,
KEY_NAME_NOT_INVALIDATED));
} else {
// Hide the purchase button which uses a non-invalidated key
// if the app doesn't work on Android N preview
purchaseButtonNotInvalidated.setVisibility(View.GONE);
findViewById(R.id.purchase_button_not_invalidated_description)
.setVisibility(View.GONE);
}
if (!keyguardManager.isKeyguardSecure()) { if (!keyguardManager.isKeyguardSecure()) {
// Show a message that the user hasn't set up a fingerprint or lock screen. // Show a message that the user hasn't set up a fingerprint or lock screen.
Toast.makeText(this, Toast.makeText(this,
@@ -104,6 +126,7 @@ public class MainActivity extends Activity {
+ "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint", + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint",
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
purchaseButton.setEnabled(false); purchaseButton.setEnabled(false);
purchaseButtonNotInvalidated.setEnabled(false);
return; return;
} }
@@ -119,62 +142,27 @@ public class MainActivity extends Activity {
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
return; return;
} }
createKey(); createKey(DEFAULT_KEY_NAME, true);
createKey(KEY_NAME_NOT_INVALIDATED, false);
purchaseButton.setEnabled(true); purchaseButton.setEnabled(true);
purchaseButton.setOnClickListener(new View.OnClickListener() { purchaseButton.setOnClickListener(
@Override new PurchaseButtonClickListener(defaultCipher, DEFAULT_KEY_NAME));
public void onClick(View v) {
findViewById(R.id.confirmation_message).setVisibility(View.GONE);
findViewById(R.id.encrypted_message).setVisibility(View.GONE);
// Set up the crypto object for later. The object will be authenticated by use
// of the fingerprint.
if (initCipher()) {
// Show the fingerprint dialog. The user has the option to use the fingerprint
// with crypto, or you can fall back to using a server-side verified password.
FingerprintAuthenticationDialogFragment fragment
= new FingerprintAuthenticationDialogFragment();
fragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
boolean useFingerprintPreference = mSharedPreferences
.getBoolean(getString(R.string.use_fingerprint_to_authenticate_key),
true);
if (useFingerprintPreference) {
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.FINGERPRINT);
} else {
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.PASSWORD);
}
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
// This happens if the lock screen has been disabled or or a fingerprint got
// enrolled. Thus show the dialog to authenticate with their password first
// and ask the user if they want to authenticate with fingerprints in the
// future
FingerprintAuthenticationDialogFragment fragment
= new FingerprintAuthenticationDialogFragment();
fragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.NEW_FINGERPRINT_ENROLLED);
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
}
}
});
} }
/** /**
* Initialize the {@link Cipher} instance with the created key in the {@link #createKey()} * Initialize the {@link Cipher} instance with the created key in the
* method. * {@link #createKey(String, boolean)} method.
* *
* @param keyName the key name to init the cipher
* @return {@code true} if initialization is successful, {@code false} if the lock screen has * @return {@code true} if initialization is successful, {@code false} if the lock screen has
* been disabled or reset after the key was generated, or if a fingerprint got enrolled after * been disabled or reset after the key was generated, or if a fingerprint got enrolled after
* the key was generated. * the key was generated.
*/ */
private boolean initCipher() { private boolean initCipher(Cipher cipher, String keyName) {
try { try {
mKeyStore.load(null); mKeyStore.load(null);
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null); SecretKey key = (SecretKey) mKeyStore.getKey(keyName, null);
mCipher.init(Cipher.ENCRYPT_MODE, key); cipher.init(Cipher.ENCRYPT_MODE, key);
return true; return true;
} catch (KeyPermanentlyInvalidatedException e) { } catch (KeyPermanentlyInvalidatedException e) {
return false; return false;
@@ -184,11 +172,19 @@ public class MainActivity extends Activity {
} }
} }
public void onPurchased(boolean withFingerprint) { /**
* Proceed the purchase operation
*
* @param withFingerprint {@code true} if the purchase was made by using a fingerprint
* @param cryptoObject the Crypto object
*/
public void onPurchased(boolean withFingerprint,
@Nullable FingerprintManager.CryptoObject cryptoObject) {
if (withFingerprint) { if (withFingerprint) {
// If the user has authenticated with fingerprint, verify that using cryptography and // If the user has authenticated with fingerprint, verify that using cryptography and
// then show the confirmation message. // then show the confirmation message.
tryEncrypt(); assert cryptoObject != null;
tryEncrypt(cryptoObject.getCipher());
} else { } else {
// Authentication happened with backup password. Just show the confirmation message. // Authentication happened with backup password. Just show the confirmation message.
showConfirmation(null); showConfirmation(null);
@@ -209,9 +205,9 @@ public class MainActivity extends Activity {
* Tries to encrypt some data with the generated key in {@link #createKey} which is * Tries to encrypt some data with the generated key in {@link #createKey} which is
* only works if the user has just authenticated via fingerprint. * only works if the user has just authenticated via fingerprint.
*/ */
private void tryEncrypt() { private void tryEncrypt(Cipher cipher) {
try { try {
byte[] encrypted = mCipher.doFinal(SECRET_MESSAGE.getBytes()); byte[] encrypted = cipher.doFinal(SECRET_MESSAGE.getBytes());
showConfirmation(encrypted); showConfirmation(encrypted);
} catch (BadPaddingException | IllegalBlockSizeException e) { } catch (BadPaddingException | IllegalBlockSizeException e) {
Toast.makeText(this, "Failed to encrypt the data with the generated key. " Toast.makeText(this, "Failed to encrypt the data with the generated key. "
@@ -223,8 +219,18 @@ public class MainActivity extends Activity {
/** /**
* Creates a symmetric key in the Android Key Store which can only be used after the user has * Creates a symmetric key in the Android Key Store which can only be used after the user has
* authenticated with fingerprint. * authenticated with fingerprint.
*
* @param keyName the name of the key to be created
* @param invalidatedByBiometricEnrollment if {@code false} is passed, the created key will not
* be invalidated even if a new fingerprint is enrolled.
* The default value is {@code true}, so passing
* {@code true} doesn't change the behavior
* (the key will be invalidated if a new fingerprint is
* enrolled.). Note that this parameter is only valid if
* the app works on Android N developer preview.
*
*/ */
public void createKey() { public void createKey(String keyName, boolean invalidatedByBiometricEnrollment) {
// The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint
// for your flow. Use of keys is necessary if you need to know if the set of // for your flow. Use of keys is necessary if you need to know if the set of
// enrolled fingerprints has changed. // enrolled fingerprints has changed.
@@ -232,15 +238,25 @@ public class MainActivity extends Activity {
mKeyStore.load(null); mKeyStore.load(null);
// Set the alias of the entry in Android KeyStore where the key will appear // Set the alias of the entry in Android KeyStore where the key will appear
// and the constrains (purposes) in the constructor of the Builder // and the constrains (purposes) in the constructor of the Builder
mKeyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,
KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(keyName,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT) KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
// Require the user to authenticate with a fingerprint to authorize every use // Require the user to authenticate with a fingerprint to authorize every use
// of the key // of the key
.setUserAuthenticationRequired(true) .setUserAuthenticationRequired(true)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);
.build());
// This is a workaround to avoid crashes on devices whose API level is < 24
// because KeyGenParameterSpec.Builder#setInvalidatedByBiometricEnrollment is only
// visible on API level +24.
// Ideally there should be a compat library for KeyGenParameterSpec.Builder but
// which isn't available yet.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setInvalidatedByBiometricEnrollment(invalidatedByBiometricEnrollment);
}
mKeyGenerator.init(builder.build());
mKeyGenerator.generateKey(); mKeyGenerator.generateKey();
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
| CertificateException | IOException e) { | CertificateException | IOException e) {
@@ -265,4 +281,54 @@ public class MainActivity extends Activity {
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private class PurchaseButtonClickListener implements View.OnClickListener {
Cipher mCipher;
String mKeyName;
PurchaseButtonClickListener(Cipher cipher, String keyName) {
mCipher = cipher;
mKeyName = keyName;
}
@Override
public void onClick(View view) {
findViewById(R.id.confirmation_message).setVisibility(View.GONE);
findViewById(R.id.encrypted_message).setVisibility(View.GONE);
// Set up the crypto object for later. The object will be authenticated by use
// of the fingerprint.
if (initCipher(mCipher, mKeyName)) {
// Show the fingerprint dialog. The user has the option to use the fingerprint with
// crypto, or you can fall back to using a server-side verified password.
FingerprintAuthenticationDialogFragment fragment
= new FingerprintAuthenticationDialogFragment();
fragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
boolean useFingerprintPreference = mSharedPreferences
.getBoolean(getString(R.string.use_fingerprint_to_authenticate_key),
true);
if (useFingerprintPreference) {
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.FINGERPRINT);
} else {
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.PASSWORD);
}
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
} else {
// This happens if the lock screen has been disabled or or a fingerprint got
// enrolled. Thus show the dialog to authenticate with their password first
// and ask the user if they want to authenticate with fingerprints in the
// future
FingerprintAuthenticationDialogFragment fragment
= new FingerprintAuthenticationDialogFragment();
fragment.setCryptoObject(new FingerprintManager.CryptoObject(mCipher));
fragment.setStage(
FingerprintAuthenticationDialogFragment.Stage.NEW_FINGERPRINT_ENROLLED);
fragment.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
}
}
}
} }

View File

@@ -21,6 +21,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/black"
tools:context="com.example.android.wearable.wear.weardrawers.MainActivity" tools:context="com.example.android.wearable.wear.weardrawers.MainActivity"
tools:deviceIds="wear"> tools:deviceIds="wear">
@@ -33,7 +34,7 @@
android:id="@+id/top_navigation_drawer" android:id="@+id/top_navigation_drawer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/dark_grey" /> android:background="@color/grey" />
<android.support.wearable.view.drawer.WearableActionDrawer <android.support.wearable.view.drawer.WearableActionDrawer
android:id="@+id/bottom_action_drawer" android:id="@+id/bottom_action_drawer"