| /* |
| * SPDX-FileCopyrightText: 2016 The CyanogenMod Project |
| * SPDX-FileCopyrightText: 2017-2024 The LineageOS Project |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| package org.lineageos.setupwizard; |
| |
| import static android.os.Binder.getCallingUserHandle; |
| import static android.os.UserHandle.USER_CURRENT; |
| |
| import static org.lineageos.setupwizard.Manifest.permission.FINISH_SETUP; |
| import static org.lineageos.setupwizard.SetupWizardApp.ACTION_FINISHED; |
| import static org.lineageos.setupwizard.SetupWizardApp.ACTION_SETUP_COMPLETE; |
| import static org.lineageos.setupwizard.SetupWizardApp.DISABLE_NAV_KEYS; |
| import static org.lineageos.setupwizard.SetupWizardApp.ENABLE_RECOVERY_UPDATE; |
| import static org.lineageos.setupwizard.SetupWizardApp.KEY_SEND_METRICS; |
| import static org.lineageos.setupwizard.SetupWizardApp.LOGV; |
| import static org.lineageos.setupwizard.SetupWizardApp.NAVIGATION_OPTION_KEY; |
| import static org.lineageos.setupwizard.SetupWizardApp.UPDATE_RECOVERY_PROP; |
| |
| import android.animation.Animator; |
| import android.animation.AnimatorListenerAdapter; |
| import android.app.WallpaperManager; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.content.om.IOverlayManager; |
| import android.content.pm.ActivityInfo; |
| import android.graphics.Bitmap; |
| import android.graphics.Point; |
| import android.graphics.Rect; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.Looper; |
| import android.os.ServiceManager; |
| import android.os.SystemProperties; |
| import android.os.UserHandle; |
| import android.util.Log; |
| import android.view.View; |
| import android.view.ViewAnimationUtils; |
| import android.view.ViewGroup.MarginLayoutParams; |
| import android.view.Window; |
| import android.widget.ImageView; |
| |
| import androidx.core.graphics.Insets; |
| import androidx.core.view.ViewCompat; |
| import androidx.core.view.WindowInsetsCompat; |
| |
| import lineageos.providers.LineageSettings; |
| |
| import org.lineageos.setupwizard.util.SetupWizardUtils; |
| |
| public class FinishActivity extends BaseSetupWizardActivity { |
| |
| public static final String TAG = FinishActivity.class.getSimpleName(); |
| |
| private ImageView mBackground; |
| |
| private SetupWizardApp mSetupWizardApp; |
| |
| private final Handler mHandler = new Handler(Looper.getMainLooper()); |
| |
| private boolean mIsFinishing; |
| |
| private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| if (LOGV) { |
| Log.v(TAG, "onReceive intent=" + intent); |
| } |
| if (intent != null && intent.getAction().equals(ACTION_FINISHED)) { |
| unregisterReceiver(mIntentReceiver); |
| completeSetup(); |
| } |
| } |
| }; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| overridePendingTransition(R.anim.translucent_enter, R.anim.translucent_exit); |
| if (LOGV) { |
| logActivityState("onCreate savedInstanceState=" + savedInstanceState); |
| } |
| mSetupWizardApp = (SetupWizardApp) getApplication(); |
| mBackground = findViewById(R.id.background); |
| setNextText(R.string.start); |
| |
| // Edge-to-edge. Needed for the background view to fill the full screen. |
| final Window window = getWindow(); |
| window.setDecorFitsSystemWindows(false); |
| |
| // Make sure 3-button navigation bar is the same color as the rest of the screen. |
| window.setNavigationBarContrastEnforced(false); |
| |
| // Ensure the main layout (not including the background view) does not get obscured by bars. |
| final View rootView = findViewById(R.id.root); |
| ViewCompat.setOnApplyWindowInsetsListener(rootView, (view, windowInsets) -> { |
| final View linearLayout = findViewById(R.id.linear_layout); |
| final Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); |
| final MarginLayoutParams params = (MarginLayoutParams) linearLayout.getLayoutParams(); |
| params.leftMargin = insets.left; |
| params.topMargin = insets.top; |
| params.rightMargin = insets.right; |
| params.bottomMargin = insets.bottom; |
| linearLayout.setLayoutParams(params); |
| return WindowInsetsCompat.CONSUMED; |
| }); |
| } |
| |
| @Override |
| protected int getLayoutResId() { |
| return R.layout.finish_activity; |
| } |
| |
| @Override |
| public void onNavigateNext() { |
| startFinishSequence(); |
| } |
| |
| private void startFinishSequence() { |
| if (mIsFinishing) { |
| return; |
| } |
| mIsFinishing = true; |
| |
| // Listen for completion from the exit service. |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction(ACTION_FINISHED); |
| registerReceiver(mIntentReceiver, filter, null, null); |
| |
| Intent i = new Intent(ACTION_SETUP_COMPLETE); |
| i.setPackage(getPackageName()); |
| sendBroadcastAsUser(i, getCallingUserHandle(), FINISH_SETUP); |
| |
| setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); |
| hideNextButton(); |
| |
| // Begin outro animation. |
| animateOut(); |
| } |
| |
| private void animateOut() { |
| final View rootView = findViewById(R.id.root); |
| final int cx = (rootView.getLeft() + rootView.getRight()) / 2; |
| final int cy = (rootView.getTop() + rootView.getBottom()) / 2; |
| final float fullRadius = (float) Math.hypot(cx, cy); |
| Animator anim = |
| ViewAnimationUtils.createCircularReveal(rootView, cx, cy, fullRadius, 0f); |
| anim.setDuration(900); |
| anim.addListener(new AnimatorListenerAdapter() { |
| @Override |
| public void onAnimationStart(Animator animation) { |
| rootView.setVisibility(View.VISIBLE); |
| } |
| |
| @Override |
| public void onAnimationEnd(Animator animation) { |
| rootView.setVisibility(View.INVISIBLE); |
| mHandler.post(() -> { |
| if (LOGV) { |
| Log.v(TAG, "Animation ended"); |
| } |
| // Start exit procedures, including the exit service. |
| SetupWizardUtils.startSetupWizardExitProcedure(FinishActivity.this); |
| }); |
| } |
| }); |
| anim.start(); |
| } |
| |
| private void completeSetup() { |
| handleEnableMetrics(mSetupWizardApp); |
| handleNavKeys(mSetupWizardApp); |
| handleRecoveryUpdate(mSetupWizardApp); |
| handleNavigationOption(mSetupWizardApp); |
| final WallpaperManager wallpaperManager = |
| WallpaperManager.getInstance(mSetupWizardApp); |
| wallpaperManager.forgetLoadedWallpaper(); |
| finishAffinity(); |
| nextAction(RESULT_OK); |
| SetupWizardUtils.enableStatusBar(); |
| Log.i(TAG, "Setup complete!"); |
| } |
| |
| private static void handleEnableMetrics(SetupWizardApp setupWizardApp) { |
| Bundle privacyData = setupWizardApp.getSettingsBundle(); |
| if (privacyData != null |
| && privacyData.containsKey(KEY_SEND_METRICS)) { |
| LineageSettings.Secure.putInt(setupWizardApp.getContentResolver(), |
| LineageSettings.Secure.STATS_COLLECTION, |
| privacyData.getBoolean(KEY_SEND_METRICS) |
| ? 1 : 0); |
| } |
| } |
| |
| private static void handleNavKeys(SetupWizardApp setupWizardApp) { |
| if (setupWizardApp.getSettingsBundle().containsKey(DISABLE_NAV_KEYS)) { |
| writeDisableNavkeysOption(setupWizardApp, |
| setupWizardApp.getSettingsBundle().getBoolean(DISABLE_NAV_KEYS)); |
| } |
| } |
| |
| private static void handleRecoveryUpdate(SetupWizardApp setupWizardApp) { |
| if (setupWizardApp.getSettingsBundle().containsKey(ENABLE_RECOVERY_UPDATE)) { |
| boolean update = setupWizardApp.getSettingsBundle() |
| .getBoolean(ENABLE_RECOVERY_UPDATE); |
| |
| SystemProperties.set(UPDATE_RECOVERY_PROP, String.valueOf(update)); |
| } |
| } |
| |
| private void handleNavigationOption(Context context) { |
| Bundle settingsBundle = mSetupWizardApp.getSettingsBundle(); |
| if (settingsBundle.containsKey(NAVIGATION_OPTION_KEY)) { |
| IOverlayManager overlayManager = IOverlayManager.Stub.asInterface( |
| ServiceManager.getService(Context.OVERLAY_SERVICE)); |
| String selectedNavMode = settingsBundle.getString(NAVIGATION_OPTION_KEY); |
| |
| try { |
| overlayManager.setEnabledExclusiveInCategory(selectedNavMode, USER_CURRENT); |
| } catch (Exception ignored) { |
| } |
| } |
| } |
| |
| private static void writeDisableNavkeysOption(Context context, boolean enabled) { |
| final boolean virtualKeysEnabled = LineageSettings.System.getIntForUser( |
| context.getContentResolver(), LineageSettings.System.FORCE_SHOW_NAVBAR, 0, |
| UserHandle.USER_CURRENT) != 0; |
| if (enabled != virtualKeysEnabled) { |
| LineageSettings.System.putIntForUser(context.getContentResolver(), |
| LineageSettings.System.FORCE_SHOW_NAVBAR, enabled ? 1 : 0, |
| UserHandle.USER_CURRENT); |
| } |
| } |
| } |