Skip to content

Merge tag 'LA.UM.5.8.r1-02700-8x98.0' of https://source.codeaurora.org/external/gigabyte/platform/packages/apps/Settings into n #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: n
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions src/com/android/settings/ChooseLockGeneric.java
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,6 @@ public void onCreate(Bundle savedInstanceState) {
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
if (mIsSetNewPassword) {
// In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user
// will be asked to confirm the password if one has been set.
// On fingerprint supported device, fingerprint options are represented in the
// options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is
// relaunched to only show options without fingerprint. In this case, we shouldn't
// ask the user to confirm the password again.
mPasswordConfirmed = getActivity().getIntent().getBooleanExtra(
PASSWORD_CONFIRMED, false);
}

if (savedInstanceState != null) {
mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
Expand Down Expand Up @@ -249,11 +239,12 @@ public boolean onPreferenceTreeClick(Preference preference) {
showFactoryResetProtectionWarningDialog(key);
return true;
} else if (KEY_SKIP_FINGERPRINT.equals(key)) {
Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
Intent chooseLockGenericIntent = new Intent(getActivity(),
ChooseLockGeneric.InternalActivity.class);
chooseLockGenericIntent.setAction(getIntent().getAction());
// Forward the target user id to ChooseLockGeneric.
chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
return true;
} else {
Expand Down
32 changes: 21 additions & 11 deletions src/com/android/settings/accounts/ManageAccountsSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import android.view.LayoutInflater;
Expand Down Expand Up @@ -83,7 +84,7 @@ public class ManageAccountsSettings extends AccountPreferenceBase

// If an account type is set, then show only accounts of that type
private String mAccountType;
// Temporary hack, to deal with backward compatibility
// Temporary hack, to deal with backward compatibility
// mFirstAccount is used for the injected preferences
private Account mFirstAccount;

Expand Down Expand Up @@ -444,15 +445,18 @@ public boolean onPreferenceClick(Preference preference) {
}

/**
* Filters through the preference list provided by GoogleLoginService.
* Recursively filters through the preference list provided by GoogleLoginService.
*
* This method removes all the invalid intent from the list, adds account name as extra into the
* intent, and hack the location settings to start it as a fragment.
*/
private void updatePreferenceIntents(PreferenceScreen prefs) {
private void updatePreferenceIntents(PreferenceGroup prefs) {
final PackageManager pm = getActivity().getPackageManager();
for (int i = 0; i < prefs.getPreferenceCount();) {
Preference pref = prefs.getPreference(i);
if (pref instanceof PreferenceGroup) {
updatePreferenceIntents((PreferenceGroup) pref);
}
Intent intent = pref.getIntent();
if (intent != null) {
// Hack. Launch "Location" as fragment instead of as activity.
Expand Down Expand Up @@ -501,8 +505,8 @@ public boolean onPreferenceClick(Preference preference) {
} else {
Log.e(TAG,
"Refusing to launch authenticator intent because"
+ "it exploits Settings permissions: "
+ prefIntent);
+ " it exploits Settings permissions: "
+ prefIntent);
}
return true;
}
Expand All @@ -522,20 +526,26 @@ public boolean onPreferenceClick(Preference preference) {
private boolean isSafeIntent(PackageManager pm, Intent intent) {
AuthenticatorDescription authDesc =
mAuthenticatorHelper.getAccountTypeDescription(mAccountType);
ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
ResolveInfo resolveInfo =
pm.resolveActivityAsUser(intent, 0, mUserHandle.getIdentifier());
if (resolveInfo == null) {
return false;
}
ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo;
ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo;
try {
if (resolvedActivityInfo.exported) {
if (resolvedActivityInfo.permission == null) {
return true; // exported activity without permission.
} else if (pm.checkPermission(resolvedActivityInfo.permission,
authDesc.packageName) == PackageManager.PERMISSION_GRANTED) {
return true;
}
}
ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
return resolvedActivityInfo.exported
|| resolvedAppInfo.uid == authenticatorAppInf.uid;
return resolvedAppInfo.uid == authenticatorAppInf.uid;
} catch (NameNotFoundException e) {
Log.e(TAG,
"Intent considered unsafe due to exception.",
e);
Log.e(TAG, "Intent considered unsafe due to exception.", e);
return false;
}
}
Expand Down
4 changes: 3 additions & 1 deletion tests/app/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle

LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
guava \
mockito-target \
espresso-core \
espresso-contrib-nodep \
espresso-intents-nodep \
ub-uiautomator
ub-uiautomator \
truth-prebuilt

# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
Expand Down
235 changes: 235 additions & 0 deletions tests/app/src/com/android/settings/ChooseLockGenericTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/*
* Copyright (C) 2017 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.settings;

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import android.support.test.runner.lifecycle.Stage;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;

import android.text.format.DateUtils;
import android.view.KeyEvent;

import com.android.settings.R;

import java.util.Collection;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;

/**
* Tests for {@link ChooseLockGenericTest}
*
* m SettingsTests &&
* adb install \
* -r -g ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk &&
* adb shell am instrument -e class com.android.settings.ChooseLockGenericTest \
* -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
public class ChooseLockGenericTest {
private static final long TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS;
private static final Intent PHISHING_ATTACK_INTENT = new Intent()
.putExtra("confirm_credentials", false)
.putExtra("password_confirmed", true);

private UiDevice mDevice;
private Context mTargetContext;
private String mSettingPackage;
private PackageManager mPackageManager;
@Rule
public ActivityTestRule<ChooseLockGeneric> mChooseLockGenericActivityRule =
new ActivityTestRule<>(
ChooseLockGeneric.class,
true /* enable touch at launch */,
false /* don't launch at every test */);

@Before
public void setUp() throws Exception {
mDevice = UiDevice.getInstance(getInstrumentation());
mTargetContext = getInstrumentation().getTargetContext();
mSettingPackage = mTargetContext.getPackageName();
mPackageManager = mTargetContext.getPackageManager();

setPassword();
}

@After
public void tearDown() throws Exception {
clearPassword();
}

@Test
public void testConfirmLockPasswordShown_deviceWithPassword() throws Exception, Throwable {
// GIVEN a PIN password is set on this device at set up.
// WHEN ChooseLockGeneric is launched with no extras.
mChooseLockGenericActivityRule.launchActivity(null /* No extras */);
// THEN ConfirmLockPassword.InternalActivity is shown.
assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
}

@Test
public void testConfirmLockPasswordShown_deviceWithPassword_phishingAttack()
throws Exception, Throwable {
// GIVEN a PIN password is set on this device at set up.
// WHEN ChooseLockGeneric is launched with extras to by-pass lock password confirmation.
mChooseLockGenericActivityRule.launchActivity(PHISHING_ATTACK_INTENT);
// THEN ConfirmLockPassword.InternalActivity is still shown.
assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
}

private Activity getCurrentActivity() throws Throwable {
getInstrumentation().waitForIdleSync();
final Activity[] activity = new Activity[1];
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance()
.getActivitiesInStage(Stage.RESUMED);
activity[0] = activities.iterator().next();
}
});
return activity[0];
}

private void launchNewPassword() throws Exception {
Intent newPasswordIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD)
.setPackage(mSettingPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getContext().startActivity(newPasswordIntent);
mDevice.waitForIdle();
}

/** Sets a PIN password, 12345, for testing. */
private void setPassword() throws Exception {
launchNewPassword();

if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
// Set "lock_none", but it actually means we don't want to enroll a fingerprint.
UiObject view = new UiObject(
new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
assertTrue("lock_none", view.waitForExists(TIMEOUT));
view.click();
mDevice.waitForIdle();
}

// Pick PIN from the option list
UiObject view = new UiObject(new UiSelector()
.resourceId(mSettingPackage + ":id/lock_pin"));
assertTrue("lock_pin", view.waitForExists(TIMEOUT));
view.click();
mDevice.waitForIdle();

// Ignore any interstitial options
view = new UiObject(new UiSelector()
.resourceId(mSettingPackage + ":id/encrypt_dont_require_password"));
if (view.waitForExists(TIMEOUT)) {
view.click();
mDevice.waitForIdle();
}

// Yes, we really want to
view = new UiObject(new UiSelector()
.resourceId(mSettingPackage + ":id/next_button"));
if (view.waitForExists(TIMEOUT)) {
view.click();
mDevice.waitForIdle();
}

// Set our PIN
view = new UiObject(new UiSelector()
.resourceId(mSettingPackage + ":id/password_entry"));
assertTrue("password_entry", view.waitForExists(TIMEOUT));

// Enter it twice to confirm
enterTestPin();
enterTestPin();

mDevice.pressBack();
}

/** Clears the previous set PIN password. */
private void clearPassword() throws Exception {
launchNewPassword();

// Enter current PIN
UiObject view = new UiObject(
new UiSelector().resourceId(mSettingPackage + ":id/password_entry"));
if (!view.waitForExists(TIMEOUT)) {
// Odd, maybe there is a crash dialog showing; try dismissing it
mDevice.pressBack();
mDevice.waitForIdle();

assertTrue("password_entry", view.waitForExists(TIMEOUT));
}

enterTestPin();

// Set back to "none"
view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
assertTrue("lock_none", view.waitForExists(TIMEOUT));
view.click();
mDevice.waitForIdle();

// Yes, we really want "none" if prompted again
view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
if (view.waitForExists(TIMEOUT)) {
view.click();
mDevice.waitForIdle();
}

// Yes, we really want to
view = new UiObject(new UiSelector()
.resourceId("android:id/button1"));
if (view.waitForExists(TIMEOUT)) {
view.click();
mDevice.waitForIdle();
}

mDevice.pressBack();
}

private void enterTestPin() throws Exception {
mDevice.waitForIdle();
mDevice.pressKeyCode(KeyEvent.KEYCODE_1);
mDevice.pressKeyCode(KeyEvent.KEYCODE_2);
mDevice.pressKeyCode(KeyEvent.KEYCODE_3);
mDevice.pressKeyCode(KeyEvent.KEYCODE_4);
mDevice.pressKeyCode(KeyEvent.KEYCODE_5);
mDevice.waitForIdle();
mDevice.pressEnter();
mDevice.waitForIdle();
}
}