android:windowSoftInputMode="stateHidden|adjustResize"
android:theme="@style/GlifTheme.Light"/>
- <activity
- android:name=".Settings$FingerprintSuggestionActivity"
- android:label="@string/security_settings_fingerprint_preference_title"
- android:icon="@drawable/ic_suggestion_fingerprint">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
- </intent-filter>
- <meta-data android:name="com.android.settings.dismiss"
- android:value="5,9,30" />
- <meta-data android:name="com.android.settings.require_feature"
- android:value="android.hardware.fingerprint" />
- <meta-data android:name="com.android.settings.title"
- android:resource="@string/suggestion_additional_fingerprints" />
- <meta-data android:name="com.android.settings.summary"
- android:resource="@string/suggestion_additional_fingerprints_summary" />
- </activity>
-
<activity android:name=".fingerprint.FingerprintSettings" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollFindSensor" android:exported="false"/>
<activity android:name=".fingerprint.FingerprintEnrollEnrolling" android:exported="false"/>
</intent-filter>
</activity>
+ <activity android:name=".fingerprint.FingerprintSuggestionActivity"
+ android:exported="true"
+ android:permission="android.permission.MANAGE_FINGERPRINT"
+ android:icon="@drawable/ic_suggestion_fingerprint"
+ android:theme="@style/GlifTheme.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.settings.suggested.category.FINGERPRINT_ENROLL" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.dismiss"
+ android:value="5,9,30" />
+ <meta-data android:name="com.android.settings.require_feature"
+ android:value="android.hardware.fingerprint" />
+ <meta-data android:name="com.android.settings.title"
+ android:resource="@string/suggestion_additional_fingerprints" />
+ <meta-data android:name="com.android.settings.summary"
+ android:resource="@string/suggestion_additional_fingerprints_summary" />
+ <meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
+ </activity>
+
<!-- Note this must not be exported since it returns the password in the intent -->
<activity android:name=".password.ConfirmLockPattern$InternalActivity"
android:exported="false"
<string name="security_settings_fingerprint_enroll_done">Done</string>
<!-- Dialog title for dialog which shows when user touches the icon on the screen, instead of the sensor at the back [CHAR LIMIT=45] -->
<string name="security_settings_fingerprint_enroll_touch_dialog_title">Whoops, that\u2019s not the sensor</string>
- <!-- Dialog message for dialog which shows when user touches the icon on the screen, instead of the sensor at the back [CHAR LIMIT=45] -->
+ <!-- Dialog message for dialog which shows when user touches the icon on the screen, instead of the sensor at the back [CHAR LIMIT=NONE] -->
<string name="security_settings_fingerprint_enroll_touch_dialog_message">Touch the sensor on the back of your phone. Use your index finger.</string>
<!-- Dialog message for dialog which shows when finger cannot be enrolled. [CHAR LIMIT=45] -->
<string name="security_settings_fingerprint_enroll_error_dialog_title">Enrollment was not completed</string>
public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ }
- public static class FingerprintSuggestionActivity extends FingerprintSettings { /* empty */ }
public static class FingerprintEnrollSuggestionActivity extends FingerprintEnrollIntroduction {
/* empty */
}
import android.util.Log;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.applications.ApplicationsState;
pref.setKey(pkgName);
pref.setTitle(appEntry.label);
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
- pref.setSummary(DateUtils.getRelativeTimeSpanString(stat.getLastTimeUsed(),
- System.currentTimeMillis(),
- DateUtils.MINUTE_IN_MILLIS,
- DateUtils.FORMAT_ABBREV_RELATIVE));
+ pref.setSummary(TextUtils.expandTemplate(
+ mContext.getResources().getText(R.string.recent_app_summary),
+ Utils.formatElapsedTime(mContext,
+ System.currentTimeMillis() - stat.getLastTimeUsed(), false)));
pref.setOrder(i);
pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
import com.android.ims.ImsManager;
import com.android.settings.Settings.CameraLiftTriggerSuggestionActivity;
import com.android.settings.Settings.FingerprintEnrollSuggestionActivity;
-import com.android.settings.Settings.FingerprintSuggestionActivity;
import com.android.settings.Settings.ScreenLockSuggestionActivity;
import com.android.settings.Settings.WifiCallingSuggestionActivity;
import com.android.settings.Settings.ZenModeAutomationSuggestionActivity;
import com.android.settings.Utils;
+import com.android.settings.fingerprint.FingerprintSuggestionActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
import com.android.settingslib.drawer.Tile;
--- /dev/null
+/*
+ * 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.fingerprint;
+
+import android.widget.Button;
+
+import com.android.settings.R;
+
+public class FingerprintSuggestionActivity extends SetupFingerprintEnrollIntroduction {
+
+ @Override
+ protected void initViews() {
+ super.initViews();
+
+ final Button cancelButton = findViewById(R.id.fingerprint_cancel_button);
+ cancelButton.setText(R.string.security_settings_fingerprint_enroll_introduction_cancel);
+ }
+
+ @Override
+ public void finish() {
+ // Always use RESULT_CANCELED because this action can be done multiple times
+ setResult(RESULT_CANCELED);
+ super.finish();
+ }
+}
final BatteryUtils batteryUtils = BatteryUtils.getInstance(context);
final long elapsedRealtimeUs =
batteryUtils.convertMsToUs(SystemClock.elapsedRealtime());
+
Intent batteryBroadcast = context.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
BatteryUtils utils = BatteryUtils.getInstance(context);
-
- if (provider != null && provider.isEnhancedBatteryPredictionEnabled(context)) {
+ // 0 means we are discharging, anything else means charging
+ boolean discharging =
+ batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
+ if (discharging && provider != null
+ && provider.isEnhancedBatteryPredictionEnabled(context)) {
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
elapsedRealtimeUs, shortString,
utils.convertMsToUs(provider.getEnhancedBatteryPrediction(context)),
} else {
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
elapsedRealtimeUs, shortString,
- stats.computeBatteryTimeRemaining(elapsedRealtimeUs), false);
+ discharging ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0,
+ false);
}
}
if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
info.remainingTimeUs = chargeTime;
CharSequence timeString = Utils.formatElapsedTime(context,
- batteryUtils.convertUsToMs(drainTimeUs), false /* withSeconds */);
+ batteryUtils.convertUsToMs(chargeTime), false /* withSeconds */);
int resId = shortString ? R.string.power_charging_duration_short
: R.string.power_charging_duration;
info.remainingLabel = TextUtils.expandTemplate(context.getText(
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
+import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.SystemClock;
import com.android.internal.os.BatteryStatsHelper;
final long elapsedRealtimeUs = batteryUtils.convertMsToUs(SystemClock.elapsedRealtime());
BatteryInfo batteryInfo;
- // Get enhanced prediction if available, otherwise use the old prediction code
+ // 0 means we are discharging, anything else means charging
+ boolean discharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
+ // Get enhanced prediction if available and discharging, otherwise use the old code
Cursor cursor = null;
- if (powerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context)) {
+ if (discharging && powerUsageFeatureProvider != null &&
+ powerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context)) {
final Uri queryUri = powerUsageFeatureProvider.getEnhancedBatteryPredictionUri();
cursor = context.getContentResolver().query(queryUri, null, null, null, null);
}
BatteryStats stats = mStatsHelper.getStats();
batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
elapsedRealtimeUs, false /* shortString */,
- stats.computeBatteryTimeRemaining(elapsedRealtimeUs), false /* basedOnUsage */);
+ discharging ? 0 : stats.computeBatteryTimeRemaining(elapsedRealtimeUs),
+ false /* basedOnUsage */);
}
return batteryInfo;
@VisibleForTesting
void restartBatteryInfoLoader() {
- if (mPowerFeatureProvider != null
- && mPowerFeatureProvider.isEnhancedBatteryPredictionEnabled(getContext())) {
- getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
- mBatteryInfoLoaderCallbacks);
- }
+ getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
+ mBatteryInfoLoaderCallbacks);
}
private static List<BatterySipper> getFakeStats() {
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
.thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats);
+ when(mMockContext.getString(eq(R.string.battery_history_minutes_no_seconds), anyInt()))
+ .thenReturn(mContext.getString(R.string.battery_history_minutes_no_seconds, 45));
mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
mController.displayPreference(mScreen);
verify(mSeeAllPref).setTitle(R.string.applications_settings);
verify(mSeeAllPref).setIcon(null);
}
+
+ @Test
+ public void display_showRecents_formatSummary() {
+ when(mMockContext.getResources().getBoolean(R.bool.config_display_recent_apps))
+ .thenReturn(true);
+ final List<UsageStats> stats = new ArrayList<>();
+ final UsageStats stat1 = new UsageStats();
+ stat1.mLastTimeUsed = System.currentTimeMillis();
+ stat1.mPackageName = "pkg.class";
+ stats.add(stat1);
+
+ when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
+ .thenReturn(mock(ApplicationsState.AppEntry.class));
+ when(mMockContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
+ .thenReturn(new ResolveInfo());
+ when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
+ .thenReturn(stats);
+ when(mMockContext.getString(eq(R.string.battery_history_minutes_no_seconds), anyInt()))
+ .thenReturn(mContext.getString(R.string.battery_history_minutes_no_seconds, 35));
+ when(mMockContext.getResources().getText(eq(R.string.recent_app_summary)))
+ .thenReturn(mContext.getResources().getText(R.string.recent_app_summary));
+
+ mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
+ mController.displayPreference(mScreen);
+
+ verify(mCategory).addPreference(argThat(summaryMatches("35m ago")));
+ }
+
+ private static ArgumentMatcher<Preference> summaryMatches(String expected) {
+ return preference -> TextUtils.equals(expected, preference.getSummary());
+ }
+
}
--- /dev/null
+/*
+ * 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.fingerprint;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.view.View;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowKeyguardManager;
+import org.robolectric.util.ActivityController;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ ShadowEventLogWriter.class,
+ ShadowLockPatternUtils.class,
+ ShadowUserManager.class
+ })
+public class FingerprintSuggestionActivityTest {
+
+ @Mock
+ private UserInfo mUserInfo;
+
+ private ActivityController<FingerprintSuggestionActivity> mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ final Intent intent = new Intent();
+ mController = Robolectric.buildActivity(FingerprintSuggestionActivity.class, intent);
+
+ ShadowUserManager.getShadow().setUserInfo(0, mUserInfo);
+ }
+
+ @Test
+ public void testKeyguardSecure_shouldFinishWithFingerprintResultSkip() {
+ getShadowKeyguardManager().setIsKeyguardSecure(true);
+
+ mController.create().resume();
+
+ final Button cancelButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+ assertThat(cancelButton.getText().toString()).isEqualTo("Cancel");
+ assertThat(cancelButton.getVisibility()).named("Cancel visible").isEqualTo(View.VISIBLE);
+ cancelButton.performClick();
+
+ ShadowActivity shadowActivity = Shadows.shadowOf(mController.get());
+ assertThat(mController.get().isFinishing()).named("Is finishing").isTrue();
+ assertThat(shadowActivity.getResultCode()).named("Result code")
+ .isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ private ShadowKeyguardManager getShadowKeyguardManager() {
+ return Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
+ }
+}
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
+import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BatteryInfoTest {
+
private static final String STATUS_FULL = "Full";
private static final String STATUS_CHARGING_NO_TIME = "50% - charging";
private static final String STATUS_CHARGING_TIME = "50% - 0m until fully charged";
private static final long REMAINING_TIME_NULL = -1;
private static final long REMAINING_TIME = 2;
public static final String ENHANCED_STRING_SUFFIX = "left based on your usage";
+ public static final long TEST_CHARGE_TIME_REMAINING = TimeUnit.MINUTES.toMicros(1);
+ public static final String TEST_CHARGE_TIME_REMAINING_STRINGIFIED =
+ "1m left until fully charged";
private Intent mDisChargingBatteryBroadcast;
private Intent mChargingBatteryBroadcast;
private Context mContext;
assertThat(info.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
assertThat(info2.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
}
+
+ @Test
+ public void testGetBatteryInfo_charging_usesChargeTime() {
+ doReturn(TEST_CHARGE_TIME_REMAINING)
+ .when(mBatteryStats)
+ .computeChargeTimeRemaining(anyLong());
+ BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
+ mBatteryStats, SystemClock.elapsedRealtime() * 1000, false, 1000, false);
+ assertThat(info.remainingTimeUs = TEST_CHARGE_TIME_REMAINING);
+ assertThat(info.remainingLabel.toString())
+ .isEqualTo(TEST_CHARGE_TIME_REMAINING_STRINGIFIED);
+ }
}
import android.content.Context;
import com.android.settings.R;
+import com.android.settings.fingerprint.FingerprintSuggestionActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@Test
public void fingerprintSuggestion_isValid() {
- assertSuggestionEquals("com.android.settings.Settings$FingerprintSuggestionActivity",
+ assertSuggestionEquals(
+ FingerprintSuggestionActivity.class.getName(),
CATEGORY_FIRST_IMPRESSION,
R.string.suggestion_additional_fingerprints,
R.string.suggestion_additional_fingerprints_summary);