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