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.permissioncontroller.permission.ui; 18 19 import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP; 20 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 21 22 import static com.android.permissioncontroller.Constants.ACTION_MANAGE_AUTO_REVOKE; 23 import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID; 24 import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID; 25 import static com.android.permissioncontroller.Constants.UNUSED_APPS_SAFETY_CENTER_SOURCE_ID; 26 import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION; 27 import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__OPENED_FOR_AUTO_REVOKE; 28 import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__OPENED_FROM_INTENT; 29 import static com.android.permissioncontroller.PermissionControllerStatsLog.AUTO_REVOKE_NOTIFICATION_CLICKED; 30 import static com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_USAGE_FRAGMENT_INTERACTION; 31 import static com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__OPEN; 32 33 import android.Manifest; 34 import android.app.ActionBar; 35 import android.content.ComponentName; 36 import android.content.Intent; 37 import android.content.pm.PackageManager; 38 import android.content.pm.PackageManager.NameNotFoundException; 39 import android.content.pm.PermissionInfo; 40 import android.os.Build; 41 import android.os.Bundle; 42 import android.os.Process; 43 import android.os.UserHandle; 44 import android.permission.PermissionManager; 45 import android.provider.Settings; 46 import android.safetycenter.SafetyCenterManager; 47 import android.safetycenter.SafetyEvent; 48 import android.safetycenter.SafetySourceData; 49 import android.util.Log; 50 import android.view.MenuItem; 51 52 import androidx.fragment.app.Fragment; 53 import androidx.navigation.NavGraph; 54 import androidx.navigation.NavInflater; 55 import androidx.navigation.Navigation; 56 import androidx.navigation.fragment.NavHostFragment; 57 58 import com.android.modules.utils.build.SdkLevel; 59 import com.android.permissioncontroller.Constants; 60 import com.android.permissioncontroller.DeviceUtils; 61 import com.android.permissioncontroller.PermissionControllerStatsLog; 62 import com.android.permissioncontroller.R; 63 import com.android.permissioncontroller.hibernation.HibernationPolicyKt; 64 import com.android.permissioncontroller.permission.ui.auto.AutoAllAppPermissionsFragment; 65 import com.android.permissioncontroller.permission.ui.auto.AutoAppPermissionsFragment; 66 import com.android.permissioncontroller.permission.ui.auto.AutoManageStandardPermissionsFragment; 67 import com.android.permissioncontroller.permission.ui.auto.AutoPermissionAppsFragment; 68 import com.android.permissioncontroller.permission.ui.auto.AutoReviewPermissionDecisionsFragment; 69 import com.android.permissioncontroller.permission.ui.auto.AutoUnusedAppsFragment; 70 import com.android.permissioncontroller.permission.ui.auto.dashboard.AutoPermissionUsageDetailsFragment; 71 import com.android.permissioncontroller.permission.ui.auto.dashboard.AutoPermissionUsageFragment; 72 import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment; 73 import com.android.permissioncontroller.permission.ui.handheld.AppPermissionGroupsFragment; 74 import com.android.permissioncontroller.permission.ui.handheld.HandheldUnusedAppsWrapperFragment; 75 import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment; 76 import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionDetailsWrapperFragment; 77 import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionUsageWrapperFragment; 78 import com.android.permissioncontroller.permission.ui.handheld.v34.AppDataSharingUpdatesFragment; 79 import com.android.permissioncontroller.permission.ui.legacy.AppPermissionActivity; 80 import com.android.permissioncontroller.permission.ui.television.TvUnusedAppsFragment; 81 import com.android.permissioncontroller.permission.ui.wear.AppPermissionsFragmentWear; 82 import com.android.permissioncontroller.permission.utils.KotlinUtils; 83 import com.android.permissioncontroller.permission.utils.PermissionMapping; 84 import com.android.permissioncontroller.permission.utils.Utils; 85 86 import java.util.Objects; 87 import java.util.Random; 88 89 /** 90 * Activity to review and manage permissions 91 */ 92 public final class ManagePermissionsActivity extends SettingsActivity { 93 private static final String LOG_TAG = ManagePermissionsActivity.class.getSimpleName(); 94 95 /** 96 * Name of the extra parameter that indicates whether or not to show all app permissions 97 */ 98 public static final String EXTRA_ALL_PERMISSIONS = 99 "com.android.permissioncontroller.extra.ALL_PERMISSIONS"; 100 101 /** 102 * Name of the extra parameter that is the fragment that called the current fragment. 103 */ 104 public static final String EXTRA_CALLER_NAME = 105 "com.android.permissioncontroller.extra.CALLER_NAME"; 106 107 // The permission group which was interacted with 108 public static final String EXTRA_RESULT_PERMISSION_INTERACTED = "com.android" 109 + ".permissioncontroller.extra.RESULT_PERMISSION_INTERACTED"; 110 /** 111 * The result of the permission in terms of {@link GrantPermissionsViewHandler.Result} 112 */ 113 public static final String EXTRA_RESULT_PERMISSION_RESULT = "com.android" 114 + ".permissioncontroller.extra.PERMISSION_RESULT"; 115 116 /** 117 * Whether to show system apps in UI receiving an intent containing this extra. 118 */ 119 public static final String EXTRA_SHOW_SYSTEM = "com.android" 120 + ".permissioncontroller.extra.SHOW_SYSTEM"; 121 122 /** 123 * Whether to show 7 days permission usage data in UI receiving an intent containing this extra. 124 */ 125 public static final String EXTRA_SHOW_7_DAYS = "com.android" 126 + ".permissioncontroller.extra.SHOW_7_DAYS"; 127 128 /** 129 * Name of the aliased activity. 130 */ 131 public static final String ALIAS_ACTIVITY_NAME = 132 "com.android.permissioncontroller.permission.ui.ManagePermissionsActivityAlias"; 133 134 /** 135 * The requestCode used when we decide not to use this activity, but instead launch 136 * another activity in our place. When that activity finishes, we set it's result 137 * as our result and then finish. 138 */ 139 private static final int PROXY_ACTIVITY_REQUEST_CODE = 5; 140 141 private static final String LAUNCH_PERMISSION_SETTINGS = 142 "android.permission.LAUNCH_PERMISSION_SETTINGS"; 143 144 private static final String APP_PERMISSIONS_SETTINGS = 145 "android.settings.APP_PERMISSIONS_SETTINGS"; 146 147 @Override onCreate(Bundle savedInstanceState)148 public void onCreate(Bundle savedInstanceState) { 149 if (DeviceUtils.isAuto(this)) { 150 // Automotive relies on a different theme. Apply before calling super so that 151 // fragments are restored properly on configuration changes. 152 setTheme(R.style.CarSettings); 153 } 154 super.onCreate(savedInstanceState); 155 156 // If this is not a phone (which uses the Navigation component), and there is a previous 157 // instance, re-use its Fragment instead of making a new one. 158 if ((DeviceUtils.isTelevision(this) || DeviceUtils.isAuto(this) 159 || DeviceUtils.isWear(this)) && savedInstanceState != null) { 160 return; 161 } 162 163 boolean provisioned = Settings.Global.getInt( 164 getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; 165 boolean completed = Settings.Secure.getInt( 166 getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; 167 if (!provisioned || !completed) { 168 Log.e(LOG_TAG, "Device setup incomplete. device provisioned=" + provisioned 169 + ", user setup complete=" + completed); 170 finishAfterTransition(); 171 return; 172 } 173 174 android.app.Fragment fragment = null; 175 Fragment androidXFragment = null; 176 String action = getIntent().getAction(); 177 178 getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 179 180 long sessionId = getIntent().getLongExtra(Constants.EXTRA_SESSION_ID, INVALID_SESSION_ID); 181 while (sessionId == INVALID_SESSION_ID) { 182 sessionId = new Random().nextLong(); 183 } 184 185 int autoRevokeAction = 186 APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__OPENED_FOR_AUTO_REVOKE; 187 int openFromIntentAction = 188 APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION__ACTION__OPENED_FROM_INTENT; 189 190 ComponentName component = getIntent().getComponent(); 191 if (component != null 192 && Objects.equals(component.getClassName(), ALIAS_ACTIVITY_NAME) 193 && !Objects.equals(action, APP_PERMISSIONS_SETTINGS)) { 194 Log.w(LOG_TAG, ALIAS_ACTIVITY_NAME + " can only be launched with " 195 + APP_PERMISSIONS_SETTINGS); 196 finishAfterTransition(); 197 return; 198 } 199 200 String permissionName; 201 switch (action) { 202 case Intent.ACTION_MANAGE_PERMISSIONS: 203 Bundle arguments = new Bundle(); 204 arguments.putLong(EXTRA_SESSION_ID, sessionId); 205 if (DeviceUtils.isAuto(this)) { 206 androidXFragment = AutoManageStandardPermissionsFragment.newInstance(); 207 androidXFragment.setArguments(arguments); 208 } else if (DeviceUtils.isTelevision(this)) { 209 androidXFragment = 210 com.android.permissioncontroller.permission.ui.television 211 .ManagePermissionsFragment.newInstance(); 212 } else { 213 setContentView(R.layout.nav_host_fragment); 214 Navigation.findNavController(this, R.id.nav_host_fragment).setGraph( 215 R.navigation.nav_graph, arguments); 216 return; 217 218 } 219 break; 220 221 case Intent.ACTION_REVIEW_PERMISSION_USAGE: { 222 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { 223 finishAfterTransition(); 224 return; 225 } 226 227 PermissionControllerStatsLog.write(PERMISSION_USAGE_FRAGMENT_INTERACTION, sessionId, 228 PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__OPEN); 229 if (DeviceUtils.isAuto(this)) { 230 androidXFragment = new AutoPermissionUsageFragment(); 231 } else { 232 androidXFragment = PermissionUsageWrapperFragment.newInstance( 233 Long.MAX_VALUE, sessionId); 234 } 235 } break; 236 237 case Intent.ACTION_REVIEW_PERMISSION_HISTORY: { 238 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { 239 finishAfterTransition(); 240 return; 241 } 242 243 String groupName = getIntent() 244 .getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME); 245 boolean showSystem = getIntent() 246 .getBooleanExtra(EXTRA_SHOW_SYSTEM, false); 247 boolean show7Days = getIntent() 248 .getBooleanExtra(EXTRA_SHOW_7_DAYS, false); 249 if (DeviceUtils.isAuto(this)) { 250 androidXFragment = AutoPermissionUsageDetailsFragment.Companion.newInstance( 251 groupName, showSystem, sessionId); 252 } else { 253 androidXFragment = PermissionDetailsWrapperFragment 254 .newInstance(groupName, Long.MAX_VALUE, showSystem, sessionId, 255 show7Days); 256 } 257 break; 258 } 259 260 case Intent.ACTION_MANAGE_APP_PERMISSION: { 261 if (DeviceUtils.isAuto(this) || DeviceUtils.isTelevision(this) 262 || DeviceUtils.isWear(this)) { 263 Intent compatIntent = new Intent(this, AppPermissionActivity.class); 264 compatIntent.putExtras(getIntent().getExtras()); 265 startActivityForResult(compatIntent, PROXY_ACTIVITY_REQUEST_CODE); 266 return; 267 } 268 String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); 269 270 if (packageName == null) { 271 Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PACKAGE_NAME"); 272 finishAfterTransition(); 273 return; 274 } 275 permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME); 276 String groupName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME); 277 278 if (permissionName == null && groupName == null) { 279 Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PERMISSION_NAME or" 280 + "EXTRA_PERMISSION_GROUP_NAME"); 281 finishAfterTransition(); 282 return; 283 } 284 285 UserHandle userHandle = getIntent().getParcelableExtra(Intent.EXTRA_USER); 286 String caller = getIntent().getStringExtra(EXTRA_CALLER_NAME); 287 288 if (groupName == null) { 289 groupName = getGroupFromPermission(permissionName); 290 } 291 292 if (groupName != null 293 && groupName.equals(Manifest.permission_group.NOTIFICATIONS)) { 294 // Redirect notification group to notification settings 295 Utils.navigateToAppNotificationSettings(this, packageName, userHandle); 296 finishAfterTransition(); 297 return; 298 } 299 300 Bundle args = AppPermissionFragment.createArgs(packageName, permissionName, 301 groupName, userHandle, caller, sessionId, null); 302 setNavGraph(args, R.id.app_permission); 303 return; 304 } 305 306 case Intent.ACTION_MANAGE_APP_PERMISSIONS: 307 case APP_PERMISSIONS_SETTINGS: { 308 if (Objects.equals(action, APP_PERMISSIONS_SETTINGS)) { 309 PermissionInfo permissionInfo; 310 try { 311 permissionInfo = getPackageManager() 312 .getPermissionInfo(LAUNCH_PERMISSION_SETTINGS, 0); 313 } catch (NameNotFoundException e) { 314 permissionInfo = null; 315 } 316 if (permissionInfo == null 317 || !Objects.equals(permissionInfo.packageName, Utils.OS_PKG)) { 318 Log.w(LOG_TAG, LAUNCH_PERMISSION_SETTINGS 319 + " must be defined by platform."); 320 finishAfterTransition(); 321 return; 322 } 323 } 324 325 String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); 326 if (packageName == null) { 327 Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PACKAGE_NAME"); 328 finishAfterTransition(); 329 return; 330 } 331 332 UserHandle userHandle = getIntent().getParcelableExtra(Intent.EXTRA_USER); 333 if (userHandle == null) { 334 userHandle = Process.myUserHandle(); 335 } 336 337 try { 338 int uid = getPackageManager().getApplicationInfoAsUser(packageName, 0, 339 userHandle).uid; 340 long settingsSessionId = getIntent().getLongExtra( 341 Intent.ACTION_AUTO_REVOKE_PERMISSIONS, INVALID_SESSION_ID); 342 if (settingsSessionId != INVALID_SESSION_ID) { 343 sessionId = settingsSessionId; 344 Log.i(LOG_TAG, "sessionId: " + sessionId 345 + " Reaching AppPermissionGroupsFragment for auto revoke. " 346 + "packageName: " + packageName + " uid " + uid); 347 PermissionControllerStatsLog.write( 348 APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION, sessionId, uid, 349 packageName, autoRevokeAction); 350 } else { 351 if (KotlinUtils.INSTANCE.isROrAutoRevokeEnabled(getApplication(), 352 packageName, userHandle)) { 353 Log.i(LOG_TAG, "sessionId: " + sessionId 354 + " Reaching AppPermissionGroupsFragment from intent. " 355 + "packageName " + packageName + " uid " + uid); 356 PermissionControllerStatsLog.write( 357 APP_PERMISSION_GROUPS_FRAGMENT_AUTO_REVOKE_ACTION, sessionId, 358 uid, packageName, openFromIntentAction); 359 } 360 } 361 } catch (PackageManager.NameNotFoundException e) { 362 // Do no logging 363 } 364 365 final boolean allPermissions = getIntent().getBooleanExtra( 366 EXTRA_ALL_PERMISSIONS, false); 367 368 369 if (DeviceUtils.isAuto(this)) { 370 if (allPermissions) { 371 androidXFragment = AutoAllAppPermissionsFragment.newInstance(packageName, 372 userHandle, sessionId); 373 } else { 374 androidXFragment = AutoAppPermissionsFragment.newInstance(packageName, 375 userHandle, sessionId, /* isSystemPermsScreen= */ true); 376 } 377 } else if (DeviceUtils.isWear(this)) { 378 androidXFragment = AppPermissionsFragmentWear.newInstance(packageName); 379 } else if (DeviceUtils.isTelevision(this)) { 380 androidXFragment = com.android.permissioncontroller.permission.ui.television 381 .AppPermissionsFragment.newInstance(packageName, userHandle); 382 } else { 383 Bundle args = AppPermissionGroupsFragment.createArgs(packageName, userHandle, 384 sessionId, /* isSystemPermsScreen= */ true); 385 setNavGraph(args, R.id.app_permission_groups); 386 return; 387 } 388 break; 389 } 390 391 case Intent.ACTION_MANAGE_PERMISSION_APPS: { 392 permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME); 393 394 String permissionGroupName = getIntent().getStringExtra( 395 Intent.EXTRA_PERMISSION_GROUP_NAME); 396 397 if (permissionGroupName == null) { 398 try { 399 PermissionInfo permInfo = getPackageManager().getPermissionInfo( 400 permissionName, 0); 401 permissionGroupName = PermissionMapping.getGroupOfPermission(permInfo); 402 } catch (PackageManager.NameNotFoundException e) { 403 Log.i(LOG_TAG, "Permission " + permissionName + " does not exist"); 404 } 405 } 406 407 if (permissionGroupName == null) { 408 permissionGroupName = permissionName; 409 } 410 411 if (permissionName == null && permissionGroupName == null) { 412 Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PERMISSION_NAME or" 413 + "EXTRA_PERMISSION_GROUP_NAME"); 414 finishAfterTransition(); 415 return; 416 } 417 418 // Redirect notification group to notification settings 419 if (permissionGroupName.equals(Manifest.permission_group.NOTIFICATIONS)) { 420 Utils.navigateToNotificationSettings(this); 421 finishAfterTransition(); 422 return; 423 } 424 425 if (Utils.isHealthPermissionUiEnabled() && permissionGroupName 426 .equals(HEALTH_PERMISSION_GROUP)) { 427 Utils.navigateToHealthConnectSettings(this); 428 finishAfterTransition(); 429 return; 430 } 431 432 if (DeviceUtils.isAuto(this)) { 433 androidXFragment = 434 AutoPermissionAppsFragment.newInstance(permissionGroupName, sessionId); 435 } else if (DeviceUtils.isTelevision(this)) { 436 androidXFragment = com.android.permissioncontroller.permission.ui.television 437 .PermissionAppsFragment.newInstance(permissionGroupName); 438 } else { 439 Bundle args = PermissionAppsFragment.createArgs(permissionGroupName, sessionId); 440 setNavGraph(args, R.id.permission_apps); 441 return; 442 } 443 } break; 444 445 case Intent.ACTION_MANAGE_UNUSED_APPS : 446 // fall through 447 case ACTION_MANAGE_AUTO_REVOKE: { 448 Log.i(LOG_TAG, "sessionId " + sessionId + " starting auto revoke fragment" 449 + " from notification"); 450 PermissionControllerStatsLog.write(AUTO_REVOKE_NOTIFICATION_CLICKED, sessionId); 451 if (SdkLevel.isAtLeastT()) { 452 SafetyCenterManager safetyCenterManager = 453 getSystemService(SafetyCenterManager.class); 454 if (safetyCenterManager.isSafetyCenterEnabled()) { 455 SafetySourceData data = safetyCenterManager.getSafetySourceData( 456 UNUSED_APPS_SAFETY_CENTER_SOURCE_ID); 457 if (data != null && !data.getIssues().isEmpty()) { 458 // Clear source data as user has reviewed their unused apps 459 HibernationPolicyKt.setUnusedAppsReviewNeeded(this, false); 460 HibernationPolicyKt.rescanAndPushDataToSafetyCenter(this, sessionId, 461 new SafetyEvent.Builder( 462 SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED) 463 .build()); 464 HibernationPolicyKt.cancelUnusedAppsNotification(this); 465 } 466 } 467 } 468 469 if (DeviceUtils.isAuto(this)) { 470 androidXFragment = AutoUnusedAppsFragment.newInstance(); 471 androidXFragment.setArguments(UnusedAppsFragment.createArgs(sessionId)); 472 } else if (DeviceUtils.isTelevision(this)) { 473 androidXFragment = TvUnusedAppsFragment.newInstance(); 474 androidXFragment.setArguments(UnusedAppsFragment.createArgs(sessionId)); 475 } else if (DeviceUtils.isWear(this)) { 476 androidXFragment = HandheldUnusedAppsWrapperFragment.newInstance(); 477 androidXFragment.setArguments(UnusedAppsFragment.createArgs(sessionId)); 478 } else { 479 setNavGraph(UnusedAppsFragment.createArgs(sessionId), R.id.auto_revoke); 480 return; 481 } 482 483 break; 484 } 485 case PermissionManager.ACTION_REVIEW_PERMISSION_DECISIONS: { 486 487 UserHandle userHandle = getIntent().getParcelableExtra(Intent.EXTRA_USER); 488 if (userHandle == null) { 489 userHandle = Process.myUserHandle(); 490 } 491 if (DeviceUtils.isAuto(this)) { 492 String source = getIntent().getStringExtra( 493 AutoReviewPermissionDecisionsFragment.EXTRA_SOURCE); 494 androidXFragment = AutoReviewPermissionDecisionsFragment.Companion 495 .newInstance(sessionId, userHandle, source); 496 } else { 497 Log.e(LOG_TAG, "ACTION_REVIEW_PERMISSION_DECISIONS is not " 498 + "supported on this device type"); 499 finishAfterTransition(); 500 return; 501 } 502 } break; 503 504 case Intent.ACTION_REVIEW_APP_DATA_SHARING_UPDATES: { 505 if (KotlinUtils.INSTANCE.isSafetyLabelChangeNotificationsEnabled(this)) { 506 setNavGraph(AppDataSharingUpdatesFragment.Companion.createArgs(sessionId), 507 R.id.app_data_sharing_updates); 508 } else { 509 finishAfterTransition(); 510 return; 511 } 512 } break; 513 514 default: { 515 Log.w(LOG_TAG, "Unrecognized action " + action); 516 finishAfterTransition(); 517 return; 518 } 519 } 520 521 if (fragment != null) { 522 getFragmentManager().beginTransaction().replace(android.R.id.content, fragment) 523 .commit(); 524 } else if (androidXFragment != null) { 525 getSupportFragmentManager().beginTransaction().replace(android.R.id.content, 526 androidXFragment).commit(); 527 } 528 } 529 getGroupFromPermission(String permissionName)530 private String getGroupFromPermission(String permissionName) { 531 try { 532 PermissionInfo permInfo = getPackageManager().getPermissionInfo( 533 permissionName, 0); 534 return PermissionMapping.getGroupOfPermission(permInfo); 535 } catch (PackageManager.NameNotFoundException e) { 536 Log.i(LOG_TAG, "Permission " + permissionName + " does not exist"); 537 } 538 return null; 539 } 540 setNavGraph(Bundle args, int startDestination)541 private void setNavGraph(Bundle args, int startDestination) { 542 setContentView(R.layout.nav_host_fragment); 543 NavHostFragment navHost = (NavHostFragment) getSupportFragmentManager() 544 .findFragmentById(R.id.nav_host_fragment); 545 NavInflater inflater = navHost.getNavController().getNavInflater(); 546 NavGraph graph = inflater.inflate(R.navigation.nav_graph); 547 graph.setStartDestination(startDestination); 548 navHost.getNavController().setGraph(graph, args); 549 } 550 551 @Override getActionBar()552 public ActionBar getActionBar() { 553 ActionBar ab = super.getActionBar(); 554 if (ab != null) { 555 ab.setHomeActionContentDescription(R.string.back); 556 } 557 return ab; 558 } 559 560 @Override onOptionsItemSelected(MenuItem item)561 public boolean onOptionsItemSelected(MenuItem item) { 562 // in automotive mode, there's no system wide back button, so need to add that 563 if (DeviceUtils.isAuto(this)) { 564 switch (item.getItemId()) { 565 case android.R.id.home: 566 onBackPressed(); 567 finishAfterTransition(); 568 return true; 569 default: 570 return super.onOptionsItemSelected(item); 571 } 572 } 573 return super.onOptionsItemSelected(item); 574 } 575 576 @Override onActivityResult(int requestCode, int resultCode, Intent data)577 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 578 super.onActivityResult(requestCode, resultCode, data); 579 if (requestCode == PROXY_ACTIVITY_REQUEST_CODE) { 580 setResult(resultCode, data); 581 finishAfterTransition(); 582 } 583 } 584 585 } 586