Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4aafac05 authored by Helen Qin's avatar Helen Qin Committed by Android (Google) Code Review
Browse files

Merge "Define all the entry-level display info in Entry."

parents a2e4669d ab4b22a3
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -30,12 +30,39 @@ import com.android.internal.util.AnnotationValidations;
 * @hide
 */
public class Entry implements Parcelable {
    // TODO: move to jetpack.
    // TODO: these constants should go to jetpack.
    public static final String VERSION = "v1";
    public static final Uri CREDENTIAL_MANAGER_ENTRY_URI = Uri.parse("credentialmanager.slice");
    public static final String HINT_TITLE = "hint_title";
    public static final String HINT_SUBTITLE = "hint_subtitle";
    public static final String HINT_ICON = "hint_icon";
    // TODO: remove these hint constants and use the credential entry & action ones defined below.
    public static final String HINT_TITLE = "HINT_TITLE";
    public static final String HINT_SUBTITLE = "HINT_SUBTITLE";
    public static final String HINT_ICON = "HINT_ICON";
    /**
     * 1. CREDENTIAL ENTRY CONSTANTS
     */
    // User profile picture associated with this credential entry.
    public static final String HINT_PROFILE_ICON = "HINT_PROFILE_ICON";
    public static final String HINT_CREDENTIAL_TYPE_ICON = "HINT_CREDENTIAL_TYPE_ICON";
     // The user account name of this provider app associated with this entry.
     // Note: this is independent from the request app.
    public static final String HINT_USER_PROVIDER_ACCOUNT_NAME = "HINT_USER_PROVIDER_ACCOUNT_NAME";
    public static final String HINT_PASSWORD_COUNT = "HINT_PASSWORD_COUNT";
    public static final String HINT_PASSKEY_COUNT = "HINT_PASSKEY_COUNT";
    public static final String HINT_TOTAL_CREDENTIAL_COUNT = "HINT_TOTAL_CREDENTIAL_COUNT";
    public static final String HINT_LAST_USED_TIME_MILLIS = "HINT_LAST_USED_TIME_MILLIS";
    /** Below are only available for get flows. */
    public static final String HINT_NOTE = "HINT_NOTE";
    public static final String HINT_USER_NAME = "HINT_USER_NAME";
    public static final String HINT_CREDENTIAL_TYPE = "HINT_CREDENTIAL_TYPE";
    public static final String HINT_PASSKEY_USER_DISPLAY_NAME = "HINT_PASSKEY_USER_DISPLAY_NAME";
    public static final String HINT_PASSWORD_VALUE = "HINT_PASSWORD_VALUE";

    /**
     * 2. ACTION CONSTANTS
     */
    public static final String HINT_ACTION_TITLE = "HINT_ACTION_TITLE";
    public static final String HINT_ACTION_SUBTEXT = "HINT_ACTION_SUBTEXT";
    public static final String HINT_ACTION_ICON = "HINT_ACTION_ICON";

    /**
    * The intent extra key for the action chip {@code Entry} list when launching the UX activities.
@@ -55,7 +82,7 @@ public class Entry implements Parcelable {
    public static final String EXTRA_ENTRY_AUTHENTICATION_ACTION =
            "android.credentials.ui.extra.ENTRY_AUTHENTICATION_ACTION";

    // TODO: may be changed to other type depending on the service implementation.
    // TODO: change to string key + string subkey.
    private final int mId;

    @NonNull
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.credentialmanager.jetpack

import android.app.slice.Slice
import android.graphics.drawable.Icon

/**
 * UI representation for a credential entry used during the get credential flow.
 *
 * TODO: move to jetpack.
 */
abstract class CredentialEntryUi(
  val credentialTypeIcon: Icon,
  val profileIcon: Icon?,
  val lastUsedTimeMillis: Long?,
  val note: CharSequence?,
) {
  companion object {
    fun fromSlice(slice: Slice): CredentialEntryUi {
      return when (slice.spec?.type) {
        TYPE_PUBLIC_KEY_CREDENTIAL -> PasskeyCredentialEntryUi.fromSlice(slice)
        TYPE_PASSWORD_CREDENTIAL -> PasswordCredentialEntryUi.fromSlice(slice)
        else -> throw IllegalArgumentException("Unexpected type: ${slice.spec?.type}")
      }
    }

    const val TYPE_PUBLIC_KEY_CREDENTIAL: String =
      "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL"
    const val TYPE_PASSWORD_CREDENTIAL: String = "androidx.credentials.TYPE_PASSWORD"
  }
}
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.credentialmanager.jetpack

import android.app.slice.Slice
import android.credentials.ui.Entry
import android.graphics.drawable.Icon

class PasskeyCredentialEntryUi(
  val userName: CharSequence,
  val userDisplayName: CharSequence?,
  credentialTypeIcon: Icon,
  profileIcon: Icon?,
  lastUsedTimeMillis: Long?,
  note: CharSequence?,
) : CredentialEntryUi(credentialTypeIcon, profileIcon, lastUsedTimeMillis, note) {
  companion object {
    fun fromSlice(slice: Slice): CredentialEntryUi {
      var userName: CharSequence? = null
      var userDisplayName: CharSequence? = null
      var credentialTypeIcon: Icon? = null
      var profileIcon: Icon? = null
      var lastUsedTimeMillis: Long? = null
      var note: CharSequence? = null

      val items = slice.items
      items.forEach {
        if (it.hasHint(Entry.HINT_USER_NAME)) {
          userName = it.text
        } else if (it.hasHint(Entry.HINT_PASSKEY_USER_DISPLAY_NAME)) {
          userDisplayName = it.text
        } else if (it.hasHint(Entry.HINT_CREDENTIAL_TYPE_ICON)) {
          credentialTypeIcon = it.icon
        } else if (it.hasHint(Entry.HINT_PROFILE_ICON)) {
          profileIcon = it.icon
        } else if (it.hasHint(Entry.HINT_LAST_USED_TIME_MILLIS)) {
          lastUsedTimeMillis = it.long
        } else if (it.hasHint(Entry.HINT_NOTE)) {
          note = it.text
        }
      }
      // TODO: fail NPE more elegantly.
      return PasskeyCredentialEntryUi(
        userName!!, userDisplayName, credentialTypeIcon!!,
        profileIcon, lastUsedTimeMillis, note,
      )
    }
  }
}
+68 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.credentialmanager.jetpack

import android.app.slice.Slice
import android.credentials.ui.Entry
import android.graphics.drawable.Icon

/**
 * UI representation for a password credential entry used during the get credential flow.
 *
 * TODO: move to jetpack.
 */
class PasswordCredentialEntryUi(
  val userName: CharSequence,
  val password: CharSequence,
  credentialTypeIcon: Icon,
  profileIcon: Icon?,
  lastUsedTimeMillis: Long?,
  note: CharSequence?,
) : CredentialEntryUi(credentialTypeIcon, profileIcon, lastUsedTimeMillis, note) {
  companion object {
    fun fromSlice(slice: Slice): CredentialEntryUi {
      var userName: CharSequence? = null
      var password: CharSequence? = null
      var credentialTypeIcon: Icon? = null
      var profileIcon: Icon? = null
      var lastUsedTimeMillis: Long? = null
      var note: CharSequence? = null

      val items = slice.items
      items.forEach {
        if (it.hasHint(Entry.HINT_USER_NAME)) {
          userName = it.text
        } else if (it.hasHint(Entry.HINT_PASSWORD_VALUE)) {
          password = it.text
        } else if (it.hasHint(Entry.HINT_CREDENTIAL_TYPE_ICON)) {
          credentialTypeIcon = it.icon
        } else if (it.hasHint(Entry.HINT_PROFILE_ICON)) {
          profileIcon = it.icon
        } else if (it.hasHint(Entry.HINT_LAST_USED_TIME_MILLIS)) {
          lastUsedTimeMillis = it.long
        } else if (it.hasHint(Entry.HINT_NOTE)) {
          note = it.text
        }
      }
      // TODO: fail NPE more elegantly.
      return PasswordCredentialEntryUi(
        userName!!, password!!, credentialTypeIcon!!,
        profileIcon, lastUsedTimeMillis, note,
      )
    }
  }
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 com.android.credentialmanager.jetpack

import android.app.slice.Slice
import android.credentials.ui.Entry
import android.graphics.drawable.Icon

/**
 * UI representation for a save entry used during the create credential flow.
 *
 * TODO: move to jetpack.
 */
class SaveEntryUi(
  val userProviderAccountName: CharSequence,
  val credentialTypeIcon: Icon?,
  val profileIcon: Icon?,
  val passwordCount: Int?,
  val passkeyCount: Int?,
  val totalCredentialCount: Int?,
  val lastUsedTimeMillis: Long?,
) {
  companion object {
    fun fromSlice(slice: Slice): SaveEntryUi {
      var userProviderAccountName: CharSequence? = null
      var credentialTypeIcon: Icon? = null
      var profileIcon: Icon? = null
      var passwordCount: Int? = null
      var passkeyCount: Int? = null
      var totalCredentialCount: Int? = null
      var lastUsedTimeMillis: Long? = null


      val items = slice.items
      items.forEach {
        if (it.hasHint(Entry.HINT_USER_PROVIDER_ACCOUNT_NAME)) {
          userProviderAccountName = it.text
        } else if (it.hasHint(Entry.HINT_CREDENTIAL_TYPE_ICON)) {
          credentialTypeIcon = it.icon
        } else if (it.hasHint(Entry.HINT_PROFILE_ICON)) {
          profileIcon = it.icon
        } else if (it.hasHint(Entry.HINT_PASSWORD_COUNT)) {
          passwordCount = it.int
        } else if (it.hasHint(Entry.HINT_PASSKEY_COUNT)) {
          passkeyCount = it.int
        } else if (it.hasHint(Entry.HINT_TOTAL_CREDENTIAL_COUNT)) {
          totalCredentialCount = it.int
        } else if (it.hasHint(Entry.HINT_LAST_USED_TIME_MILLIS)) {
          lastUsedTimeMillis = it.long
        }
      }
      // TODO: fail NPE more elegantly.
      return SaveEntryUi(
        userProviderAccountName!!, credentialTypeIcon, profileIcon,
        passwordCount, passkeyCount, totalCredentialCount, lastUsedTimeMillis,
      )
    }
  }
}