1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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 17 package com.android.settingslib.dream; 18 19 import static android.service.dreams.Flags.allowDreamWhenPostured; 20 21 import android.annotation.IntDef; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.ResolveInfo; 28 import android.content.pm.ServiceInfo; 29 import android.content.res.Resources; 30 import android.graphics.drawable.Drawable; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.UserHandle; 34 import android.provider.Settings; 35 import android.service.dreams.DreamService; 36 import android.service.dreams.IDreamManager; 37 import android.util.ArraySet; 38 import android.util.Log; 39 40 import com.android.internal.annotations.VisibleForTesting; 41 import com.android.internal.util.FrameworkStatsLog; 42 43 import java.lang.annotation.Retention; 44 import java.lang.annotation.RetentionPolicy; 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.Comparator; 48 import java.util.List; 49 import java.util.Set; 50 import java.util.stream.Collectors; 51 52 public class DreamBackend { 53 private static final String TAG = "DreamBackend"; 54 private static final boolean DEBUG = false; 55 56 public static class DreamInfo { 57 public CharSequence caption; 58 public Drawable icon; 59 public boolean isActive; 60 public ComponentName componentName; 61 public ComponentName settingsComponentName; 62 public CharSequence description; 63 public Drawable previewImage; 64 public boolean supportsComplications = false; 65 public int dreamCategory; 66 67 @Override toString()68 public String toString() { 69 StringBuilder sb = new StringBuilder(DreamInfo.class.getSimpleName()); 70 sb.append('[').append(caption); 71 if (isActive) { 72 sb.append(",active"); 73 } 74 sb.append(',').append(componentName); 75 if (settingsComponentName != null) { 76 sb.append("settings=").append(settingsComponentName); 77 } 78 return sb.append(']').toString(); 79 } 80 } 81 82 @Retention(RetentionPolicy.SOURCE) 83 @IntDef({ 84 WHILE_CHARGING, 85 WHILE_DOCKED, 86 WHILE_POSTURED, 87 WHILE_CHARGING_OR_DOCKED, 88 NEVER 89 }) 90 public @interface WhenToDream { 91 } 92 93 public static final int WHILE_CHARGING = 0; 94 public static final int WHILE_DOCKED = 1; 95 public static final int WHILE_POSTURED = 2; 96 public static final int WHILE_CHARGING_OR_DOCKED = 3; 97 public static final int NEVER = 4; 98 99 /** 100 * The type of dream complications which can be provided by a 101 * {@link com.android.systemui.dreams.ComplicationProvider}. 102 */ 103 @IntDef(prefix = {"COMPLICATION_TYPE_"}, value = { 104 COMPLICATION_TYPE_TIME, 105 COMPLICATION_TYPE_DATE, 106 COMPLICATION_TYPE_WEATHER, 107 COMPLICATION_TYPE_AIR_QUALITY, 108 COMPLICATION_TYPE_CAST_INFO, 109 COMPLICATION_TYPE_HOME_CONTROLS, 110 COMPLICATION_TYPE_SMARTSPACE, 111 COMPLICATION_TYPE_MEDIA_ENTRY 112 }) 113 @Retention(RetentionPolicy.SOURCE) 114 public @interface ComplicationType { 115 } 116 117 public static final int COMPLICATION_TYPE_TIME = 1; 118 public static final int COMPLICATION_TYPE_DATE = 2; 119 public static final int COMPLICATION_TYPE_WEATHER = 3; 120 public static final int COMPLICATION_TYPE_AIR_QUALITY = 4; 121 public static final int COMPLICATION_TYPE_CAST_INFO = 5; 122 public static final int COMPLICATION_TYPE_HOME_CONTROLS = 6; 123 public static final int COMPLICATION_TYPE_SMARTSPACE = 7; 124 public static final int COMPLICATION_TYPE_MEDIA_ENTRY = 8; 125 126 private static final int SCREENSAVER_HOME_CONTROLS_ENABLED_DEFAULT = 1; 127 private static final int LOCKSCREEN_SHOW_CONTROLS_DEFAULT = 0; 128 129 private static final int DS_TYPE_ENABLED = FrameworkStatsLog 130 .DREAM_SETTING_CHANGED__DREAM_SETTING_TYPE__DREAM_SETTING_TYPE_ENABLED; 131 private static final int DS_TYPE_WHEN_TO_DREAM = FrameworkStatsLog 132 .DREAM_SETTING_CHANGED__DREAM_SETTING_TYPE__DREAM_SETTING_TYPE_WHEN_TO_DREAM; 133 private static final int DS_TYPE_DREAM_COMPONENT = FrameworkStatsLog 134 .DREAM_SETTING_CHANGED__DREAM_SETTING_TYPE__DREAM_SETTING_TYPE_DREAM_COMPONENT; 135 private static final int DS_TYPE_SHOW_ADDITIONAL_INFO = FrameworkStatsLog 136 .DREAM_SETTING_CHANGED__DREAM_SETTING_TYPE__DREAM_SETTING_TYPE_SHOW_ADDITIONAL_INFO; 137 private static final int DS_TYPE_SHOW_HOME_CONTROLS = FrameworkStatsLog 138 .DREAM_SETTING_CHANGED__DREAM_SETTING_TYPE__DREAM_SETTING_TYPE_SHOW_HOME_CONTROLS; 139 140 private static final int WHEN_TO_DREAM_UNSPECIFIED = FrameworkStatsLog 141 .DREAM_SETTING_CHANGED__WHEN_TO_DREAM__WHEN_TO_DREAM_UNSPECIFIED; 142 private static final int WHEN_TO_DREAM_CHARGING = FrameworkStatsLog 143 .DREAM_SETTING_CHANGED__WHEN_TO_DREAM__WHEN_TO_DREAM_WHILE_CHARGING_ONLY; 144 private static final int WHEN_TO_DREAM_DOCKED = FrameworkStatsLog 145 .DREAM_SETTING_CHANGED__WHEN_TO_DREAM__WHEN_TO_DREAM_WHILE_DOCKED_ONLY; 146 private static final int WHEN_TO_DREAM_POSTURED = FrameworkStatsLog 147 .DREAM_SETTING_CHANGED__WHEN_TO_DREAM__WHEN_TO_DREAM_WHILE_POSTURED_ONLY; 148 private static final int WHEN_TO_DREAM_CHARGING_OR_DOCKED = FrameworkStatsLog 149 .DREAM_SETTING_CHANGED__WHEN_TO_DREAM__WHEN_TO_DREAM_EITHER_CHARGING_OR_DOCKED; 150 151 private final Context mContext; 152 private final IDreamManager mDreamManager; 153 private final DreamInfoComparator mComparator; 154 private final boolean mDreamsEnabledByDefault; 155 private final boolean mDreamsActivatedOnSleepByDefault; 156 private final boolean mDreamsActivatedOnDockByDefault; 157 private final boolean mDreamsActivatedOnPosturedByDefault; 158 private final Set<ComponentName> mDisabledDreams; 159 private final List<String> mLoggableDreamPrefixes; 160 private Set<Integer> mSupportedComplications; 161 private static DreamBackend sInstance; 162 getInstance(Context context)163 public static DreamBackend getInstance(Context context) { 164 if (sInstance == null) { 165 sInstance = new DreamBackend(context); 166 } 167 return sInstance; 168 } 169 DreamBackend(Context context)170 public DreamBackend(Context context) { 171 mContext = context.getApplicationContext(); 172 final Resources resources = mContext.getResources(); 173 174 mDreamManager = IDreamManager.Stub.asInterface( 175 ServiceManager.getService(DreamService.DREAM_SERVICE)); 176 mComparator = new DreamInfoComparator(getDefaultDream()); 177 mDreamsEnabledByDefault = resources.getBoolean( 178 com.android.internal.R.bool.config_dreamsEnabledByDefault); 179 mDreamsActivatedOnSleepByDefault = resources.getBoolean( 180 com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault); 181 mDreamsActivatedOnDockByDefault = resources.getBoolean( 182 com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault); 183 mDreamsActivatedOnPosturedByDefault = resources.getBoolean( 184 com.android.internal.R.bool.config_dreamsActivatedOnPosturedByDefault); 185 mDisabledDreams = Arrays.stream(resources.getStringArray( 186 com.android.internal.R.array.config_disabledDreamComponents)) 187 .map(ComponentName::unflattenFromString) 188 .collect(Collectors.toSet()); 189 mLoggableDreamPrefixes = Arrays.stream(resources.getStringArray( 190 com.android.internal.R.array.config_loggable_dream_prefixes)).toList(); 191 192 mSupportedComplications = Arrays.stream(resources.getIntArray( 193 com.android.internal.R.array.config_supportedDreamComplications)) 194 .boxed() 195 .collect(Collectors.toSet()); 196 } 197 getDreamInfos()198 public List<DreamInfo> getDreamInfos() { 199 logd("getDreamInfos()"); 200 ComponentName activeDream = getActiveDream(); 201 PackageManager pm = mContext.getPackageManager(); 202 Intent dreamIntent = new Intent(DreamService.SERVICE_INTERFACE); 203 List<ResolveInfo> resolveInfos = pm.queryIntentServices(dreamIntent, 204 PackageManager.GET_META_DATA); 205 List<DreamInfo> dreamInfos = new ArrayList<>(resolveInfos.size()); 206 for (ResolveInfo resolveInfo : resolveInfos) { 207 final ComponentName componentName = getDreamComponentName(resolveInfo); 208 if (componentName == null || mDisabledDreams.contains(componentName)) { 209 continue; 210 } 211 212 DreamInfo dreamInfo = new DreamInfo(); 213 dreamInfo.caption = resolveInfo.loadLabel(pm); 214 dreamInfo.icon = resolveInfo.loadIcon(pm); 215 dreamInfo.description = getDescription(resolveInfo, pm); 216 dreamInfo.componentName = componentName; 217 dreamInfo.isActive = dreamInfo.componentName.equals(activeDream); 218 219 final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata( 220 mContext.getPackageManager(), resolveInfo.serviceInfo); 221 if (dreamMetadata != null) { 222 dreamInfo.settingsComponentName = dreamMetadata.settingsActivity; 223 dreamInfo.previewImage = dreamMetadata.previewImage; 224 dreamInfo.supportsComplications = dreamMetadata.showComplications; 225 dreamInfo.dreamCategory = dreamMetadata.dreamCategory; 226 } 227 dreamInfos.add(dreamInfo); 228 } 229 dreamInfos.sort(mComparator); 230 return dreamInfos; 231 } 232 getDescription(ResolveInfo resolveInfo, PackageManager pm)233 private static CharSequence getDescription(ResolveInfo resolveInfo, PackageManager pm) { 234 String packageName = resolveInfo.resolvePackageName; 235 ApplicationInfo applicationInfo = null; 236 if (packageName == null) { 237 packageName = resolveInfo.serviceInfo.packageName; 238 applicationInfo = resolveInfo.serviceInfo.applicationInfo; 239 } 240 if (resolveInfo.serviceInfo.descriptionRes != 0) { 241 return pm.getText(packageName, 242 resolveInfo.serviceInfo.descriptionRes, 243 applicationInfo); 244 } 245 return null; 246 } 247 getDefaultDream()248 public ComponentName getDefaultDream() { 249 if (mDreamManager == null) { 250 return null; 251 } 252 try { 253 return mDreamManager.getDefaultDreamComponentForUser(mContext.getUserId()); 254 } catch (RemoteException e) { 255 Log.w(TAG, "Failed to get default dream", e); 256 return null; 257 } 258 } 259 getActiveDreamName()260 public CharSequence getActiveDreamName() { 261 ComponentName cn = getActiveDream(); 262 if (cn != null) { 263 PackageManager pm = mContext.getPackageManager(); 264 try { 265 ServiceInfo ri = pm.getServiceInfo(cn, 0); 266 if (ri != null) { 267 return ri.loadLabel(pm); 268 } 269 } catch (PackageManager.NameNotFoundException exc) { 270 return null; // uninstalled? 271 } 272 } 273 return null; 274 } 275 276 /** 277 * Gets an icon from active dream. 278 */ getActiveIcon()279 public Drawable getActiveIcon() { 280 final ComponentName cn = getActiveDream(); 281 if (cn != null) { 282 final PackageManager pm = mContext.getPackageManager(); 283 try { 284 final ServiceInfo ri = pm.getServiceInfo(cn, 0); 285 if (ri != null) { 286 return ri.loadIcon(pm); 287 } 288 } catch (PackageManager.NameNotFoundException exc) { 289 return null; 290 } 291 } 292 return null; 293 } 294 295 @WhenToDream getWhenToDreamSetting()296 public int getWhenToDreamSetting() { 297 return isActivatedOnDock() && isActivatedOnSleep() ? WHILE_CHARGING_OR_DOCKED 298 : isActivatedOnSleep() ? WHILE_CHARGING 299 : isActivatedOnDock() ? WHILE_DOCKED 300 : isActivatedOnPostured() ? WHILE_POSTURED 301 : NEVER; 302 } 303 setWhenToDream(@henToDream int whenToDream)304 public void setWhenToDream(@WhenToDream int whenToDream) { 305 setEnabled(whenToDream != NEVER); 306 307 switch (whenToDream) { 308 case WHILE_CHARGING: 309 setActivatedOnDock(false); 310 setActivatedOnSleep(true); 311 setActivatedOnPostured(false); 312 break; 313 314 case WHILE_DOCKED: 315 setActivatedOnDock(true); 316 setActivatedOnSleep(false); 317 setActivatedOnPostured(false); 318 break; 319 320 case WHILE_CHARGING_OR_DOCKED: 321 setActivatedOnDock(true); 322 setActivatedOnSleep(true); 323 setActivatedOnPostured(false); 324 break; 325 326 case WHILE_POSTURED: 327 setActivatedOnPostured(true); 328 setActivatedOnSleep(false); 329 setActivatedOnDock(false); 330 break; 331 332 case NEVER: 333 default: 334 break; 335 } 336 337 logDreamSettingChangeToStatsd(DS_TYPE_WHEN_TO_DREAM); 338 } 339 340 /** Gets all complications which have been enabled by the user. */ getEnabledComplications()341 public Set<Integer> getEnabledComplications() { 342 final Set<Integer> enabledComplications = 343 getComplicationsEnabled() 344 ? new ArraySet<>(mSupportedComplications) : new ArraySet<>(); 345 346 if (!getHomeControlsEnabled()) { 347 enabledComplications.remove(COMPLICATION_TYPE_HOME_CONTROLS); 348 } else if (mSupportedComplications.contains(COMPLICATION_TYPE_HOME_CONTROLS)) { 349 // Add home control type to list of enabled complications, even if other complications 350 // have been disabled. 351 enabledComplications.add(COMPLICATION_TYPE_HOME_CONTROLS); 352 } 353 return enabledComplications; 354 } 355 356 /** Sets complication enabled state. */ setComplicationsEnabled(boolean enabled)357 public void setComplicationsEnabled(boolean enabled) { 358 Settings.Secure.putInt(mContext.getContentResolver(), 359 Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED, enabled ? 1 : 0); 360 logDreamSettingChangeToStatsd(DS_TYPE_SHOW_ADDITIONAL_INFO); 361 } 362 363 /** Sets whether home controls are enabled by the user on the dream */ setHomeControlsEnabled(boolean enabled)364 public void setHomeControlsEnabled(boolean enabled) { 365 Settings.Secure.putInt(mContext.getContentResolver(), 366 Settings.Secure.SCREENSAVER_HOME_CONTROLS_ENABLED, enabled ? 1 : 0); 367 logDreamSettingChangeToStatsd(DS_TYPE_SHOW_HOME_CONTROLS); 368 } 369 370 /** Gets whether home controls button is enabled on the dream */ getHomeControlsEnabled()371 private boolean getHomeControlsEnabled() { 372 return Settings.Secure.getInt( 373 mContext.getContentResolver(), 374 Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 375 LOCKSCREEN_SHOW_CONTROLS_DEFAULT) == 1 376 && Settings.Secure.getInt( 377 mContext.getContentResolver(), 378 Settings.Secure.SCREENSAVER_HOME_CONTROLS_ENABLED, 379 SCREENSAVER_HOME_CONTROLS_ENABLED_DEFAULT) == 1; 380 } 381 382 /** 383 * Gets whether complications are enabled on this device 384 */ getComplicationsEnabled()385 public boolean getComplicationsEnabled() { 386 return Settings.Secure.getInt( 387 mContext.getContentResolver(), 388 Settings.Secure.SCREENSAVER_COMPLICATIONS_ENABLED, 1) == 1; 389 } 390 391 /** Gets all dream complications which are supported on this device. **/ getSupportedComplications()392 public Set<Integer> getSupportedComplications() { 393 return mSupportedComplications; 394 } 395 396 /** 397 * Sets the list of supported complications. Should only be used in tests. 398 */ 399 @VisibleForTesting setSupportedComplications(Set<Integer> complications)400 public void setSupportedComplications(Set<Integer> complications) { 401 mSupportedComplications = complications; 402 } 403 isEnabled()404 public boolean isEnabled() { 405 return getBoolean(Settings.Secure.SCREENSAVER_ENABLED, mDreamsEnabledByDefault); 406 } 407 setEnabled(boolean value)408 public void setEnabled(boolean value) { 409 logd("setEnabled(%s)", value); 410 setBoolean(Settings.Secure.SCREENSAVER_ENABLED, value); 411 logDreamSettingChangeToStatsd(DS_TYPE_ENABLED); 412 } 413 isActivatedOnDock()414 public boolean isActivatedOnDock() { 415 return getBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, 416 mDreamsActivatedOnDockByDefault); 417 } 418 setActivatedOnDock(boolean value)419 public void setActivatedOnDock(boolean value) { 420 logd("setActivatedOnDock(%s)", value); 421 setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, value); 422 } 423 isActivatedOnSleep()424 public boolean isActivatedOnSleep() { 425 return getBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 426 mDreamsActivatedOnSleepByDefault); 427 } 428 setActivatedOnSleep(boolean value)429 public void setActivatedOnSleep(boolean value) { 430 logd("setActivatedOnSleep(%s)", value); 431 setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, value); 432 } 433 isActivatedOnPostured()434 public boolean isActivatedOnPostured() { 435 return allowDreamWhenPostured() 436 && getBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED, 437 mDreamsActivatedOnPosturedByDefault); 438 } 439 440 /** 441 * Sets whether dreams should be activated when the device is postured (stationary and upright) 442 */ setActivatedOnPostured(boolean value)443 public void setActivatedOnPostured(boolean value) { 444 if (allowDreamWhenPostured()) { 445 logd("setActivatedOnPostured(%s)", value); 446 setBoolean(Settings.Secure.SCREENSAVER_ACTIVATE_ON_POSTURED, value); 447 } 448 } 449 getBoolean(String key, boolean def)450 private boolean getBoolean(String key, boolean def) { 451 return Settings.Secure.getInt(mContext.getContentResolver(), key, def ? 1 : 0) == 1; 452 } 453 setBoolean(String key, boolean value)454 private void setBoolean(String key, boolean value) { 455 Settings.Secure.putInt(mContext.getContentResolver(), key, value ? 1 : 0); 456 } 457 setActiveDream(ComponentName dream)458 public void setActiveDream(ComponentName dream) { 459 logd("setActiveDream(%s)", dream); 460 if (mDreamManager == null) { 461 return; 462 } 463 try { 464 ComponentName[] dreams = {dream}; 465 mDreamManager.setDreamComponents(dream == null ? null : dreams); 466 logDreamSettingChangeToStatsd(DS_TYPE_DREAM_COMPONENT); 467 } catch (RemoteException e) { 468 Log.w(TAG, "Failed to set active dream to " + dream, e); 469 } 470 } 471 getActiveDream()472 public ComponentName getActiveDream() { 473 if (mDreamManager == null) { 474 return null; 475 } 476 try { 477 ComponentName[] dreams = mDreamManager.getDreamComponents(); 478 return dreams != null && dreams.length > 0 ? dreams[0] : null; 479 } catch (RemoteException e) { 480 Log.w(TAG, "Failed to get active dream", e); 481 return null; 482 } 483 } 484 launchSettings(Context uiContext, DreamInfo dreamInfo)485 public void launchSettings(Context uiContext, DreamInfo dreamInfo) { 486 logd("launchSettings(%s)", dreamInfo); 487 if (dreamInfo == null || dreamInfo.settingsComponentName == null) { 488 return; 489 } 490 final Intent intent = new Intent() 491 .setComponent(dreamInfo.settingsComponentName) 492 .addFlags( 493 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 494 uiContext.startActivity(intent); 495 } 496 497 /** 498 * Preview a dream, given the component name. 499 */ preview(ComponentName componentName)500 public void preview(ComponentName componentName) { 501 logd("preview(%s)", componentName); 502 if (mDreamManager == null || componentName == null) { 503 return; 504 } 505 try { 506 mDreamManager.testDream(mContext.getUserId(), componentName); 507 } catch (RemoteException e) { 508 Log.w(TAG, "Failed to preview " + componentName, e); 509 } 510 } 511 startDreaming()512 public void startDreaming() { 513 logd("startDreaming()"); 514 if (mDreamManager == null) { 515 return; 516 } 517 try { 518 mDreamManager.dream(); 519 } catch (RemoteException e) { 520 Log.w(TAG, "Failed to dream", e); 521 } 522 } 523 getDreamComponentName(ResolveInfo resolveInfo)524 private static ComponentName getDreamComponentName(ResolveInfo resolveInfo) { 525 if (resolveInfo == null || resolveInfo.serviceInfo == null) { 526 return null; 527 } 528 return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); 529 } 530 logd(String msg, Object... args)531 private static void logd(String msg, Object... args) { 532 if (DEBUG) { 533 Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args)); 534 } 535 } 536 logDreamSettingChangeToStatsd(int dreamSettingType)537 private void logDreamSettingChangeToStatsd(int dreamSettingType) { 538 FrameworkStatsLog.write( 539 FrameworkStatsLog.DREAM_SETTING_CHANGED, /*atom_tag*/ 540 UserHandle.myUserId(), /*uid*/ 541 isEnabled(), /*enabled*/ 542 getActiveDreamComponentForStatsd(), /*dream_component*/ 543 getWhenToDreamForStatsd(), /*when_to_dream*/ 544 getComplicationsEnabled(), /*show_additional_info*/ 545 getHomeControlsEnabled(), /*show_home_controls*/ 546 dreamSettingType /*dream_setting_type*/ 547 ); 548 } 549 550 /** 551 * Returns the user selected dream component in string format for stats logging. If the dream 552 * component is not loggable, returns "other". 553 */ getActiveDreamComponentForStatsd()554 private String getActiveDreamComponentForStatsd() { 555 final ComponentName activeDream = getActiveDream(); 556 if (activeDream == null) { 557 return ""; 558 } 559 560 final String component = activeDream.flattenToShortString(); 561 if (isLoggableDreamComponentForStatsd(component)) { 562 return component; 563 } else { 564 return "other"; 565 } 566 } 567 568 /** 569 * Whether the dream component is loggable. Only components from the predefined packages are 570 * allowed to be logged for privacy. 571 */ isLoggableDreamComponentForStatsd(String component)572 private boolean isLoggableDreamComponentForStatsd(String component) { 573 for (int i = 0; i < mLoggableDreamPrefixes.size(); i++) { 574 if (component.startsWith(mLoggableDreamPrefixes.get(i))) { 575 return true; 576 } 577 } 578 579 return false; 580 } 581 582 /** 583 * Returns the enum of "when to dream" setting for statsd logging. 584 */ getWhenToDreamForStatsd()585 private int getWhenToDreamForStatsd() { 586 switch (getWhenToDreamSetting()) { 587 case WHILE_CHARGING: 588 return WHEN_TO_DREAM_CHARGING; 589 case WHILE_DOCKED: 590 return WHEN_TO_DREAM_DOCKED; 591 case WHILE_POSTURED: 592 return WHEN_TO_DREAM_POSTURED; 593 case WHILE_CHARGING_OR_DOCKED: 594 return WHEN_TO_DREAM_CHARGING_OR_DOCKED; 595 case NEVER: 596 default: 597 return WHEN_TO_DREAM_UNSPECIFIED; 598 } 599 } 600 601 private static class DreamInfoComparator implements Comparator<DreamInfo> { 602 private final ComponentName mDefaultDream; 603 DreamInfoComparator(ComponentName defaultDream)604 public DreamInfoComparator(ComponentName defaultDream) { 605 mDefaultDream = defaultDream; 606 } 607 608 @Override compare(DreamInfo lhs, DreamInfo rhs)609 public int compare(DreamInfo lhs, DreamInfo rhs) { 610 return sortKey(lhs).compareTo(sortKey(rhs)); 611 } 612 sortKey(DreamInfo di)613 private String sortKey(DreamInfo di) { 614 StringBuilder sb = new StringBuilder(); 615 sb.append(di.componentName.equals(mDefaultDream) ? '0' : '1'); 616 sb.append(di.caption); 617 return sb.toString(); 618 } 619 } 620 } 621