SetupWizard: Part 2: Implement new OOBE using custom wizard manager

Change-Id: Ie6beb6395c5a4936384e78d57c95262e302220f9
This commit is contained in:
cretin45
2016-04-25 11:00:04 -07:00
parent 3593f035fc
commit d4cea55dd7
87 changed files with 5006 additions and 5074 deletions

View File

@@ -5,9 +5,10 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE_TAGS := optional
LOCAL_PACKAGE_NAME := CyanogenSetupWizard
LOCAL_PACKAGE_NAME := LineageSetupWizard
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_OVERRIDES_PACKAGES := Provision
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod Project
Copyright (C) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -65,26 +66,54 @@
android:taskAffinity="com.android.wizard"
android:name=".SetupWizardApp">
<activity android:name=".ui.SetupWizardActivity"
android:label="@string/product_name"
android:launchMode="singleInstance"
<activity android:theme="@style/NoDisplay"
android:label="@string/activity_label_empty"
android:name=".wizardmanager.WizardManager"
android:exported="true"
android:excludeFromRecents="true"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:immersive="true">
<intent-filter>
<action android:name="com.android.wizard.LOAD" />
<action android:name="com.android.wizard.NEXT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".SetupWizardActivity"
android:label="@string/activity_label_empty"
android:lockTaskMode="normal"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:immersive="true"
android:windowSoftInputMode="stateAlwaysHidden"
android:theme="@style/NoDisplay">
<intent-filter android:priority="9">
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.DEVICE_INITIALIZATION_WIZARD" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.SETUP_WIZARD"/>
</intent-filter>
</activity>
<activity android:name=".BluetoothSetupActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_BLUETOOTH_SETUP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- <intent-filter android:priority="9">
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.DEVICE_INITIALIZATION_WIZARD" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter> -->
</activity>
<activity android:name=".ui.WelcomeActivity"
android:label="@string/product_name"
<activity android:name=".WelcomeActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
@@ -95,8 +124,8 @@
</intent-filter>
</activity>
<activity android:name=".ui.LocaleActivity"
android:label="@string/product_name"
<activity android:name=".LocaleActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
@@ -107,8 +136,98 @@
</intent-filter>
</activity>
<activity android:name=".ui.LineageSettingsActivity"
android:label="@string/product_name"
<activity android:name=".DateTimeActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_DATETIME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".WifiSetupActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_WIFI_SETUP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".CaptivePortalSetupActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_CAPTIVE_PORTAL_SETUP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".SimMissingActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_SIM_MISSING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".ChooseDataSimActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_CHOOSE_DATA_SIM" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".MobileDataActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_ENABLE_MOBILE_DATA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".LocationSettingsActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_LOCATION_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".LineageSettingsActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
@@ -119,8 +238,34 @@
</intent-filter>
</activity>
<activity android:name=".ui.FinishActivity"
android:label="@string/product_name"
<activity android:name=".FingerprintActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_FINGERPRINT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".ScreenLockActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
android:exported="false"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.LINEAGE_LOCKSCREEN_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".FinishActivity"
android:label="@string/activity_label_empty"
android:excludeFromRecents="true"
android:configChanges="mcc|mnc"
android:immersive="true"
@@ -131,10 +276,33 @@
</intent-filter>
</activity>
<activity android:name=".SetupWizardExitActivity"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:excludeFromRecents="true"
android:immersive="true"
android:label="@@string/activity_label_empty"
android:theme="@style/NoDisplay">
<intent-filter>
<action android:name="com.cyanogenmod.setupwizard.EXIT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".SetupWizardTestActivity"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:exported="false"
android:immersive="true"
android:label="@string/activity_label_empty"
android:launchMode="singleInstance"
android:theme="@style/NoDisplay"/>
<receiver android:name=".PartnerReceiver">
<intent-filter>
<action android:name="com.android.setupwizard.action.PARTNER_CUSTOMIZATION" />
</intent-filter>
</receiver>
<service android:name=".SetupWizardExitService"
android:exported="false"/>
</application>
</manifest>

13
exit_wizard.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
adb root
wait ${!}
adb shell pm enable com.cyanogenmod.setupwizard/com.cyanogenmod.setupwizard.SetupWizardExitActivity || true
wait ${!}
adb shell pm enable com.google.android.setupwizard/com.google.android.setupwizard.SetupWizardExitActivity || true
wait ${!}
sleep 1
adb shell am start com.cyanogenmod.setupwizard/com.cyanogenmod.setupwizard.SetupWizardExitActivity || true
wait ${!}
sleep 1
adb shell am start com.google.android.setupwizard/com.google.android.setupwizard.SetupWizardExitActivity

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 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.
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="100%"
android:toXDelta="0%"
android:interpolator="@android:anim/decelerate_interpolator" />

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 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.
-->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="100%"
android:interpolator="@android:anim/decelerate_interpolator" />

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 The LineageOS 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/header_condensed" />
<com.cyanogenmod.setupwizard.ui.LocalePicker
android:id="@+id/locale_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_centerInParent="true"/>
</LinearLayout>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ImageView
android:id="@+id/brand_logo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/logo"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:padding="@dimen/content_margin_left"/>
</LinearLayout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The CyanogenMod Project
Copyright (C) 2017 The LineageOS 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/button_bar_background">
<Button
style="@style/ButtonBar.Left"
android:id="@+id/prev_button"
android:layout_width="0dp"
android:background="?android:attr/selectableItemBackground"
android:layout_weight="3"/>
<Button
style="@style/ButtonBar.Right"
android:id="@+id/next_button"
android:layout_width="0dp"
android:background="?android:attr/selectableItemBackground"
android:text="@string/next"
android:layout_weight="2" />
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -63,4 +64,7 @@
android:layout_gravity="top"
android:visibility="gone"/>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -15,7 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.cyanogenmod.setupwizard.ui.widget.ScrimInsetsFrameLayout
<com.cyanogenmod.setupwizard.widget.ScrimInsetsFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
@@ -25,6 +25,7 @@
android:clickable="true"
android:fitsSystemWindows="true"
app:insetForeground="@android:color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -54,6 +55,7 @@
style="@style/setup_wizard_navbar_style" />
</LinearLayout>
<ImageView android:id="@+id/reveal"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -67,4 +69,5 @@
android:layout_height="8dp"
android:layout_gravity="bottom"
android:visibility="gone"/>
</com.cyanogenmod.setupwizard.ui.widget.ScrimInsetsFrameLayout>
</com.cyanogenmod.setupwizard.widget.ScrimInsetsFrameLayout>

View File

@@ -25,7 +25,7 @@
android:paddingTop="22dip"
android:paddingBottom="22dip"/>
<view class="com.cyanogenmod.setupwizard.ui.LocalePicker$CustomEditText"
<view class="com.cyanogenmod.setupwizard.widget.LocalePicker$CustomEditText"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
android:id="@+id/localepicker_input"

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod Project
Copyright (C) 2017 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -154,4 +156,7 @@
</LinearLayout>
</ScrollView>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -27,7 +28,8 @@
style="?android:attr/progressBarStyleHorizontal"
android:indeterminateOnly="true"
android:layout_width="match_parent"
android:layout_height="8dp" />
android:layout_height="8dp"
android:visibility="gone"/>
<FrameLayout android:id="@+id/page"
android:layout_width="match_parent"
@@ -43,8 +45,7 @@
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/PageContent"
android:visibility="gone">
style="@style/PageContent">
<TextView
android:id="@+id/mobile_data_summary"
@@ -102,4 +103,7 @@
</LinearLayout>
</ScrollView>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -1,251 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The CyanogenMod Project
Copyright (C) 2017 The LineageOS 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/header_condensed" />
<FrameLayout android:id="@+id/page"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/PageContent">
<!-- The caption about privacy policy -->
<TextView
android:id="@+id/privacy_policy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_marginBottom="@dimen/summary_margin_bottom"
android:paddingLeft="@dimen/content_margin_left"
android:paddingRight="@dimen/content_margin_right"
style="@style/PageSummaryText"
android:text="@string/services_explanation"
android:clickable="true"/>
<LinearLayout
android:id="@+id/killswitch"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/location_margin_left"
android:paddingRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground">
<ImageView
android:id="@+id/killswitch_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingLeft="8dp"
android:paddingRight="@dimen/location_text_margin_left"
android:layout_gravity="center|top"
android:src="@drawable/tick"/>
<RelativeLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom">
<TextView
android:id="@+id/killswitch_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:fadingEdge="horizontal"
android:text="@string/setup_require_cyanogen_label"/>
<TextView
android:id="@+id/killswitch_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/killswitch_title"
android:layout_alignStart="@+id/killswitch_title"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/setup_device_locked_instructions"/>
</RelativeLayout>
</LinearLayout>
<!-- Whether or not to enable metrics -->
<LinearLayout
android:id="@+id/metrics"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/location_margin_left"
android:paddingRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/enable_metrics_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false"/>
<TextView
android:id="@+id/enable_metrics_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_metrics_label"/>
</LinearLayout>
<!-- Whether or not to enable default theme -->
<LinearLayout
android:id="@+id/theme"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/location_margin_left"
android:paddingRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/enable_theme_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false"/>
<TextView
android:id="@+id/enable_theme_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_metrics_label"/>
</LinearLayout>
<!-- Checkbox for using on-screen nav keys -->
<LinearLayout
android:id="@+id/nav_keys"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/location_margin_left"
android:paddingRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/nav_keys_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false" />
<TextView
android:id="@+id/nav_keys_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_os_nav_keys_label"/>
</LinearLayout>
<LinearLayout
android:id="@+id/privacy_guard"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/location_margin_left"
android:paddingRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/privacy_guard_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false" />
<TextView
android:id="@+id/privacy_guard_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:lineSpacingExtra="@dimen/setup_line_spacing"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_os_privacy_guard"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -110,4 +111,7 @@
</LinearLayout>
</ScrollView>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -88,4 +89,7 @@
</LinearLayout>
</ScrollView>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod Project
Copyright (C) 2017 The LineageOS 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primary">
<Space android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
<ImageView
android:id="@+id/brand_logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/logo"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:padding="@dimen/content_margin_left"/>
<Space android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -36,4 +37,8 @@
android:layout_height="0dp"
android:layout_weight="1"
style="@style/PageContent"/>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -31,7 +31,7 @@
android:paddingLeft="@dimen/content_margin_left"
android:paddingRight="@dimen/content_margin_left">
<com.cyanogenmod.setupwizard.ui.LocalePicker
<com.cyanogenmod.setupwizard.widget.LocalePicker
android:id="@+id/locale_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -66,4 +67,7 @@
</LinearLayout>
</ScrollView>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod 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.
-->
<com.cyanogenmod.setupwizard.ui.widget.ScrimInsetsFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/root"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:fitsSystemWindows="true"
app:insetForeground="@android:color/transparent">
<LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
style="@style/PageContainer"/>
<include layout="@layout/button_bar"/>
</LinearLayout>
<ImageView android:id="@+id/reveal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/reveal"
android:visibility="invisible"/>
<ProgressBar
android:id="@+id/finishing_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
android:layout_gravity="bottom"
android:visibility="gone"/>
</com.cyanogenmod.setupwizard.ui.widget.ScrimInsetsFrameLayout>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The CyanogenMod Project
Copyright (C) 2017 The LineageOS 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primary">
<Space android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
<ImageView
android:id="@+id/brand_logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/logo"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:padding="@dimen/content_margin_left"/>
<Space android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@color/primary">
<include layout="@layout/header_condensed" />
@@ -54,4 +55,7 @@
</LinearLayout>
</FrameLayout>
<fragment android:name="com.android.setupwizard.navigationbar.SetupWizardNavBar"
android:id="@+id/navigation_bar"
style="@style/setup_wizard_navbar_style" />
</LinearLayout>

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod Project
Copyright (C) 2017 The LineageOS 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.
-->
<WizardScript xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard"
wizard:firstAction="bluetooth_setup">
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_BLUETOOTH_SETUP;end" id="bluetooth_setup">
<result wizard:action="welcome" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_WELCOME;end" id="welcome">
<result wizard:action="locale" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_LOCALE;end" id="locale">
<result wizard:action="datetime" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_DATETIME;end" id="datetime">
<result wizard:action="wifi_setup" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_WIFI_SETUP;end" id="wifi_setup">
<result wizard:resultCode="1" wizard:action="sim_missing" wizard:name="no_sim" />
<result wizard:action="choose_data_sim" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SIM_MISSING;end" id="sim_missing">
<result wizard:resultCode="1" wizard:action="location_settings" wizard:name="skip_sim" />
<result wizard:action="choose_data_sim" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_CHOOSE_DATA_SIM;end" id="choose_data_sim">
<result wizard:action="enable_mobile_data" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_ENABLE_MOBILE_DATA;end" id="enable_mobile_data">
<result wizard:action="location_settings" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_LOCATION_SETTINGS;end" id="location_settings">
<result wizard:action="lineage_settings" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SETTINGS;end" id="lineage_settings">
<result wizard:action="fingerprint_settings" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_FINGERPRINT_SETTINGS;end" id="fingerprint_settings">
<result wizard:action="lockscreen_settings" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_LOCKSCREEN_SETTINGS;end" id="lockscreen_settings">
<result wizard:action="finish" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SETUP_COMPLETE;end" id="finish">
<result wizard:action="exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.EXIT;end" id="exit" />
</WizardScript>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod 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.
-->
<WizardScript xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard"
wizard:firstAction="welcome">
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_WELCOME;end" id="welcome">
<result wizard:action="finish" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SETUP_COMPLETE;end" id="finish">
<result wizard:action="exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.EXIT;end" id="exit" />
</WizardScript>

11
res/raw/wizard_script.xml Executable file → Normal file
View File

@@ -25,12 +25,8 @@
adb shell am to-intent-uri -a com.android.setupwizard.WELCOME -f 0x10000000 \-\-ez firstRun true
-->
<WizardScript wizard:firstAction="oem_pre_setup"
<WizardScript wizard:firstAction="welcome"
xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard">
<!-- Preliminary setup for OEMs -->
<WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.OEM_PRE_SETUP;end" id="oem_pre_setup">
<result wizard:action="welcome" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_WELCOME;end" id="welcome">
<result wizard:action="locale" />
</WizardAction>
@@ -80,5 +76,8 @@
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SETUP_COMPLETE;end" id="finish">
<result wizard:action="exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.EXIT;end" id="exit" />
<WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.EXIT;end" id="exit">
<result wizard:action="cm_exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.EXIT;end" id="cm_exit" />
</WizardScript>

5
res/raw/wizard_script_user.xml Executable file → Normal file
View File

@@ -77,5 +77,8 @@
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.LINEAGE_SETUP_COMPLETE;end" id="oem_post_setup">
<result wizard:action="exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.EXIT;end" id="exit" />
<WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.EXIT;end" id="exit">
<result wizard:action="cm_exit" />
</WizardAction>
<WizardAction wizard:uri="intent:#Intent;action=com.cyanogenmod.setupwizard.EXIT;end" id="cm_exit" />
</WizardScript>

View File

@@ -21,10 +21,14 @@
<string name="os_name" translatable="false">LineageOS</string>
<string name="default_theme_name" translatable="false">Material</string>
<string name="cm_wizard_script_uri" translatable="false">android.resource://com.cyanogenmod.setupwizard/raw/cm_wizard_script</string>
<string name="cm_wizard_script_user_uri" translatable="false">android.resource://com.cyanogenmod.setupwizard/raw/cm_wizard_script_user</string>
<!-- Partner SUW Strings -->
<string name="theme_type" translatable="false">material_light</string>
<string name="wizard_script_uri" translatable="false">android.resource://com.cyanogenmod.setupwizard/raw/wizard_script</string>
<string name="wizard_script_user_uri" translatable="false">android.resource://com.cyanogenmod.setupwizard/raw/wizard_script_user</string>
<string name="activity_label_empty" />
<string name="next">Next</string>
<string name="skip">Skip</string>

View File

@@ -111,4 +111,6 @@
<item name="internalMaxHeight">180dip</item>
<item name="virtualButtonPressedDrawable">@null</item>
</style>
<style name="NoDisplay" parent="@android:style/Theme.NoDisplay" />
</resources>

View File

@@ -0,0 +1,667 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.android.setupwizardlib.util.ResultCodes.RESULT_ACTIVITY_NOT_FOUND;
import static com.android.setupwizardlib.util.ResultCodes.RESULT_RETRY;
import static com.android.setupwizardlib.util.ResultCodes.RESULT_SKIP;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_EMERGENCY_DIAL;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_NEXT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_ACTION_ID;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_FIRST_RUN;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_HAS_MULTIPLE_USERS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_RESULT_CODE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_SCRIPT_URI;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_USE_IMMERSIVE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.setupwizard.navigationbar.SetupWizardNavBar;
import com.android.setupwizard.navigationbar.SetupWizardNavBar.NavigationBarListener;
import com.android.setupwizardlib.util.SystemBarHelper;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.util.List;
public abstract class BaseSetupWizardActivity extends Activity implements NavigationBarListener {
public static final String TAG = BaseSetupWizardActivity.class.getSimpleName();
protected static final int TRANSITION_ID_NONE = -1;
protected static final int TRANSITION_ID_DEFAULT = 1;
protected static final int TRANSITION_ID_SLIDE = 2;
protected static final int TRANSITION_ID_FADE = 3;
protected static final int NEXT_REQUEST = 10000;
protected static final int EMERGENCY_DIAL_ACTIVITY_REQUEST = 10038;
protected static final int WIFI_ACTIVITY_REQUEST = 10004;
protected static final int BLUETOOTH_ACTIVITY_REQUEST = 10100;
protected static final int FINGERPRINT_ACTIVITY_REQUEST = 10101;
protected static final int SCREENLOCK_ACTIVITY_REQUEST = 10102;
private SetupWizardNavBar mNavigationBar;
protected boolean mIsActivityVisible = false;
protected boolean mIsExiting = false;
private boolean mIsFirstRun = true;
protected boolean mIsGoingBack = false;
private boolean mIsPrimaryUser;
private int mResultCode = 0;
private Intent mResultData;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (LOGV) {
logActivityState("onCreate savedInstanceState=" + savedInstanceState);
}
super.onCreate(savedInstanceState);
mIsPrimaryUser = UserHandle.myUserId() == 0;
initLayout();
}
@Override
protected void onStart() {
if (LOGV) {
logActivityState("onStart");
}
super.onStart();
exitIfSetupComplete();
}
@Override
protected void onRestart() {
if (LOGV) {
logActivityState("onRestart");
}
super.onRestart();
}
@Override
protected void onResume() {
if (LOGV) {
logActivityState("onResume");
}
super.onResume();
if (mIsGoingBack) {
if (!mIsExiting) {
applyBackwardTransition(getTransition());
}
} else if (!mIsExiting) {
applyForwardTransition(getTransition());
}
}
@Override
protected void onPause() {
if (LOGV) {
logActivityState("onPause");
}
super.onPause();
}
@Override
protected void onStop() {
if (LOGV) {
logActivityState("onStop");
}
super.onStop();
}
@Override
protected void onDestroy() {
if (LOGV) {
logActivityState("onDestroy");
}
super.onDestroy();
}
@Override
public void onAttachedToWindow() {
if (LOGV) {
logActivityState("onAttachedToWindow");
}
mIsActivityVisible = true;
super.onAttachedToWindow();
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
if (LOGV) {
Log.v(TAG, "onRestoreInstanceState(" + savedInstanceState + ")");
}
super.onRestoreInstanceState(savedInstanceState);
int currentId = savedInstanceState.getInt("currentFocus", -1);
if (currentId != -1) {
View view = findViewById(currentId);
if (view != null) {
view.requestFocus();
}
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
View current = getCurrentFocus();
outState.putInt("currentFocus", current != null ? current.getId() : -1);
if (LOGV) {
Log.v(TAG, "onSaveInstanceState(" + outState + ")");
}
}
@Override
public void onNavigationBarCreated(SetupWizardNavBar bar) {
mNavigationBar = bar;
bar.setUseImmersiveMode(true);
bar.getView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
view.requestApplyInsets();
}
});
}
protected void setBackDrawable(Drawable drawable) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setCompoundDrawables(drawable, null, null, null);
}
}
protected void setNextDrawable(Drawable drawable) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setCompoundDrawables(null, null, drawable, null);
}
}
public void setBackAllowed(boolean allowed) {
SystemBarHelper.setBackButtonVisible(getWindow(), allowed);
if (mNavigationBar != null) {
Button backButton = mNavigationBar.getBackButton();
backButton.setEnabled(allowed);
}
}
protected boolean isBackAllowed() {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().isEnabled();
}
return false;
}
public void setNextAllowed(boolean allowed) {
if (mNavigationBar != null) {
mNavigationBar.getNextButton().setEnabled(allowed);
}
}
protected boolean isNextAllowed() {
if (mNavigationBar != null) {
mNavigationBar.getNextButton().isEnabled();
}
return false;
}
protected void onNextPressed() {
nextAction(NEXT_REQUEST);
}
protected void setNextText(int resId) {
if (mNavigationBar != null) {
mNavigationBar.getNextButton().setText(resId);
}
}
protected void setBackText(int resId) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setText(resId);
}
}
protected void hideNextButton() {
if (mNavigationBar != null) {
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
final Button next = mNavigationBar.getNextButton();
next.startAnimation(fadeOut);
next.setVisibility(View.INVISIBLE);
}
}
protected Intent getResultData() {
return null;
}
@Override
public void onBackPressed() {
if (LOGV) {
Log.v(TAG, "onBackPressed()");
}
setResultCode(RESULT_CANCELED, getResultData());
super.onBackPressed();
}
public void onNavigateBack() {
onBackPressed();
}
public void onNavigateNext() {
onNextPressed();
}
protected void startEmergencyDialer() {
try {
startFirstRunActivityForResult(new Intent(ACTION_EMERGENCY_DIAL),
EMERGENCY_DIAL_ACTIVITY_REQUEST);
applyForwardTransition(TRANSITION_ID_DEFAULT);
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Can't find the emergency dialer: com.android.phone.EmergencyDialer.DIAL");
}
}
protected void onSetupStart() {
SetupWizardUtils.disableCaptivePortalDetection(getApplicationContext());
SetupWizardUtils.disableStatusBar(getApplicationContext());
SystemBarHelper.hideSystemBars(getWindow());
tryEnablingWifi();
}
protected void exitIfSetupComplete() {
if (WizardManagerHelper.isUserSetupComplete(this)) {
Log.i(TAG, "Starting activity with USER_SETUP_COMPLETE=true");
startSetupWizardExitActivity();
setResult(RESULT_CANCELED, null);
finishAllAppTasks();
}
}
protected void finishAllAppTasks() {
List<ActivityManager.AppTask> appTasks =
getSystemService(ActivityManager.class).getAppTasks();
for (ActivityManager.AppTask task : appTasks) {
if (LOGV) {
Log.v(TAG, "Finishing task=" + task.toString());
}
task.finishAndRemoveTask();
}
finish();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (LOGV) {
Log.v(TAG, "onActivityResult(" + getRequestName(requestCode) + ", " +
getResultName(requestCode, resultCode) + ")");
}
mIsGoingBack = true;
if (requestCode != NEXT_REQUEST || resultCode != RESULT_CANCELED) {
if (requestCode == EMERGENCY_DIAL_ACTIVITY_REQUEST) {
applyBackwardTransition(TRANSITION_ID_DEFAULT);
return;
}
if (resultCode == RESULT_CANCELED) {
finish();
} else {
nextAction(resultCode);
}
}
}
public void finish() {
if (LOGV) {
Log.v(TAG, "finish");
}
super.finish();
if (isResumed() && mResultCode == RESULT_CANCELED) {
applyBackwardTransition(getTransition());
}
mIsExiting = true;
}
protected void finishAction() {
finishAction(RESULT_CANCELED);
}
protected void finishAction(int resultCode) {
finishAction(resultCode, null);
}
protected void finishAction(int resultCode, Intent data) {
if (resultCode != 0) {
nextAction(resultCode, data);
}
finish();
}
protected void setResultCode(int resultCode) {
setResultCode(resultCode, getResultData());
}
protected void setResultCode(int resultCode, Intent data) {
if (LOGV) {
Log.v(TAG, "setResultCode result=" + getResultName(0, resultCode) + " data=" + data);
}
mResultCode = resultCode;
mResultData = data;
setResult(resultCode, data);
}
protected void nextAction(int resultCode) {
nextAction(resultCode, null);
}
protected void nextAction(int resultCode, Intent data) {
if (LOGV) {
Log.v(TAG, "nextAction resultCode=" + resultCode +
" data=" + data + " this=" + this);
}
if (resultCode == 0) {
throw new IllegalArgumentException("Cannot call nextAction with RESULT_CANCELED");
}
setResultCode(resultCode, data);
sendActionResults();
}
public void startActivity(Intent intent) {
super.startActivity(intent);
if (isResumed() && mIsActivityVisible) {
applyForwardTransition(getTransition());
}
mIsExiting = true;
}
public void startActivityForResult(Intent intent, int requestCode) {
super.startActivityForResult(intent, requestCode);
if (isResumed() && mIsActivityVisible) {
applyForwardTransition(getTransition());
}
mIsExiting = true;
}
protected void sendActionResults() {
if (LOGV) {
Log.v(TAG, "sendActionResults resultCode=" + mResultCode + " data=" + mResultData);
}
Intent intent = new Intent(ACTION_NEXT);
intent.putExtra(EXTRA_SCRIPT_URI, getIntent().getStringExtra(EXTRA_SCRIPT_URI));
intent.putExtra(EXTRA_ACTION_ID, getIntent().getStringExtra(EXTRA_ACTION_ID));
intent.putExtra(EXTRA_RESULT_CODE, mResultCode);
if (!(mResultData == null || mResultData.getExtras() == null)) {
intent.putExtras(mResultData.getExtras());
}
startActivityForResult(intent, NEXT_REQUEST);
}
protected void applyForwardTransition(int transitionId) {
if (transitionId == TRANSITION_ID_SLIDE) {
overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
} else if (transitionId == TRANSITION_ID_FADE) {
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
} else if (transitionId == TRANSITION_ID_DEFAULT) {
TypedArray typedArray = obtainStyledAttributes(android.R.style.Animation_Activity,
new int[]{android.R.attr.activityOpenEnterAnimation,
android.R.attr.activityOpenExitAnimation});
overridePendingTransition(typedArray.getResourceId(0, 0),
typedArray.getResourceId(1, 0));
typedArray.recycle();
} else if (transitionId == TRANSITION_ID_NONE) {
overridePendingTransition(0, 0);
}
}
protected void applyBackwardTransition(int transitionId) {
if (transitionId == TRANSITION_ID_SLIDE) {
overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
} else if (transitionId == TRANSITION_ID_FADE) {
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
} else if (transitionId == TRANSITION_ID_DEFAULT) {
TypedArray typedArray = obtainStyledAttributes(android.R.style.Animation_Activity,
new int[]{android.R.attr.activityCloseEnterAnimation,
android.R.attr.activityCloseExitAnimation});
overridePendingTransition(typedArray.getResourceId(0, 0),
typedArray.getResourceId(1, 0));
typedArray.recycle();
} else if (transitionId == TRANSITION_ID_NONE) {
overridePendingTransition(0, 0);
}
}
protected void hideBackButton() {
if (mNavigationBar != null) {
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
final Button back = mNavigationBar.getBackButton();
back.startAnimation(fadeOut);
back.setVisibility(View.INVISIBLE);
}
}
protected int getTransition() {
return TRANSITION_ID_DEFAULT;
}
protected boolean tryEnablingWifi() {
WifiManager wifiManager = getSystemService(WifiManager.class);
if (wifiManager != null && !wifiManager.isWifiEnabled()) {
return wifiManager.setWifiEnabled(true);
}
return false;
}
private void startSetupWizardExitActivity() {
if (LOGV) {
Log.v(TAG, "startSetupWizardExitActivity()");
}
startFirstRunActivity(new Intent(this, SetupWizardExitActivity.class));
}
protected void startFirstRunActivity(Intent intent) {
if (LOGV) {
Log.v(TAG, "starting activity " + intent);
}
intent.putExtra(EXTRA_FIRST_RUN, isFirstRun());
intent.putExtra(EXTRA_HAS_MULTIPLE_USERS, hasMultipleUsers());
intent.putExtra(EXTRA_USE_IMMERSIVE, true);
startActivity(intent);
}
protected void startFirstRunActivityForResult(Intent intent, int requestCode) {
if (LOGV) {
Log.v(TAG, "startFirstRunActivityForResult requestCode=" + requestCode);
}
intent.putExtra(EXTRA_FIRST_RUN, isFirstRun());
intent.putExtra(EXTRA_HAS_MULTIPLE_USERS, hasMultipleUsers());
intent.putExtra(EXTRA_USE_IMMERSIVE, true);
startActivityForResult(intent, requestCode);
}
protected boolean isFirstRun() {
return mIsFirstRun;
}
protected boolean isPrimaryUser() {
return mIsPrimaryUser;
}
public boolean hasMultipleUsers() {
return ((UserManager) getSystemService(USER_SERVICE)).getUsers().size() > 1;
}
protected void logActivityState(String prefix) {
Log.v(TAG, prefix + " isResumed=" + isResumed() + " isFinishing=" +
isFinishing() + " isDestroyed=" + isDestroyed());
}
protected static String getRequestName(int requestCode) {
StringBuilder sb = new StringBuilder();
switch (requestCode) {
case NEXT_REQUEST:
sb.append("NEXT_REQUEST");
break;
case EMERGENCY_DIAL_ACTIVITY_REQUEST:
sb.append("EMERGENCY_DIAL_ACTIVITY_REQUEST");
break;
case WIFI_ACTIVITY_REQUEST:
sb.append("WIFI_ACTIVITY_REQUEST");
break;
case BLUETOOTH_ACTIVITY_REQUEST:
sb.append("BLUETOOTH_ACTIVITY_REQUEST");
break;
case FINGERPRINT_ACTIVITY_REQUEST:
sb.append("FINGERPRINT_ACTIVITY_REQUEST");
break;
case SCREENLOCK_ACTIVITY_REQUEST:
sb.append("SCREENLOCK_ACTIVITY_REQUEST");
break;
}
sb.append("(").append(requestCode).append(")");
return sb.toString();
}
protected static String getResultName(int requestCode, int resultCode) {
StringBuilder sb = new StringBuilder();
switch (requestCode) {
case WIFI_ACTIVITY_REQUEST:
switch (resultCode) {
case RESULT_OK:
sb.append("RESULT_OK");
break;
case RESULT_CANCELED:
sb.append("RESULT_CANCELED");
break;
case RESULT_SKIP:
sb.append("RESULT_WIFI_SKIP");
break;
default:
break;
}
case BLUETOOTH_ACTIVITY_REQUEST:
switch (resultCode) {
case RESULT_OK:
sb.append("RESULT_OK");
break;
case RESULT_CANCELED:
sb.append("RESULT_CANCELED");
break;
case RESULT_SKIP:
sb.append("RESULT_BLUETOOTH_SKIP");
break;
default:
break;
}
case FINGERPRINT_ACTIVITY_REQUEST:
switch (resultCode) {
case RESULT_OK:
sb.append("RESULT_OK");
break;
case RESULT_CANCELED:
sb.append("RESULT_CANCELED");
break;
case RESULT_SKIP:
sb.append("RESULT_BLUETOOTH_SKIP");
break;
default:
break;
}
case SCREENLOCK_ACTIVITY_REQUEST:
switch (resultCode) {
case RESULT_OK:
sb.append("RESULT_OK");
break;
case RESULT_CANCELED:
sb.append("RESULT_CANCELED");
break;
case RESULT_SKIP:
sb.append("RESULT_SCREENLOCK_SKIP");
break;
default:
break;
}
default:
switch (resultCode) {
case RESULT_OK:
sb.append("RESULT_OK");
break;
case RESULT_CANCELED:
sb.append("RESULT_CANCELED");
break;
case RESULT_SKIP:
sb.append("RESULT_SKIP");
break;
case RESULT_RETRY:
sb.append("RESULT_RETRY");
break;
case RESULT_ACTIVITY_NOT_FOUND:
sb.append("RESULT_ACTIVITY_NOT_FOUND");
break;
}
break;
}
sb.append("(").append(resultCode).append(")");
return sb.toString();
}
private void initLayout() {
if (getLayoutResId() != -1) {
setContentView(getLayoutResId());
}
if (getTitleResId() != -1) {
TextView title = (TextView) findViewById(android.R.id.title);
title.setText(getTitleResId());
}
if (getIconResId() != -1) {
ImageView icon = (ImageView) findViewById(R.id.header_icon);
icon.setImageResource(getIconResId());
icon.setVisibility(View.VISIBLE);
}
}
protected int getLayoutResId() {
return -1;
}
protected int getTitleResId() {
return -1;
}
protected int getIconResId() {
return -1;
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.REQUEST_CODE_SETUP_BLUETOOTH;
import android.content.Intent;
import android.util.Log;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class BluetoothSetupActivity extends SubBaseActivity {
public static final String TAG = BluetoothSetupActivity.class.getSimpleName();
private static final String ACTION_CONNECT_INPUT =
"com.google.android.intent.action.CONNECT_INPUT";
private static final String INTENT_EXTRA_NO_INPUT_MODE = "no_input_mode";
@Override
protected void onStartSubactivity() {
try {
Intent intent = new Intent();
intent.setComponent(SetupWizardUtils.mTvAddAccessorySettingsActivity);
intent.setAction(ACTION_CONNECT_INPUT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(INTENT_EXTRA_NO_INPUT_MODE, true);
startSubactivity(intent, REQUEST_CODE_SETUP_BLUETOOTH);
} catch (Exception e) {
Log.e(TAG, "Error starting bluetooth setup", e);
nextAction(RESULT_OK);
SetupWizardUtils.disableComponent(this, BluetoothSetupActivity.class);
finish();
}
}
@Override
protected int getSubactivityNextTransition() {
return TRANSITION_ID_SLIDE;
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.REQUEST_CODE_SETUP_CAPTIVE_PORTAL;
import android.content.Context;
import android.content.Intent;
import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
import android.os.AsyncTask;
import android.provider.Settings;
import android.util.Log;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
public class CaptivePortalSetupActivity extends SubBaseActivity {
public static final String TAG = CaptivePortalSetupActivity.class.getSimpleName();
private static final String DEFAULT_SERVER = "clients3.google.com";
private static final int CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS = 10000;
private URL mCaptivePortalUrl;
@Override
protected void onStartSubactivity() {
String server = Settings.Global.getString(getContentResolver(), "captive_portal_server");
if (server == null) server = DEFAULT_SERVER;
try {
mCaptivePortalUrl = new URL("http://" + server + "/generate_204");
} catch (MalformedURLException e) {
Log.e(TAG, "Not a valid url" + e);
}
CheckForCaptivePortalTask
.checkForCaptivePortal(mCaptivePortalUrl, this, true);
}
@Override
protected int getSubactivityNextTransition() {
return TRANSITION_ID_FADE;
}
private static class CheckForCaptivePortalTask extends AsyncTask<Void, Void, Boolean> {
private final URL captivePortalUrl;
private final CaptivePortalSetupActivity captivePortalSetupActivity;
private static CheckForCaptivePortalTask sTask = null;
private String responseToken;
public CheckForCaptivePortalTask(URL captivePortalUrl,
CaptivePortalSetupActivity captivePortalSetupActivity) {
this.captivePortalUrl = captivePortalUrl;
this.captivePortalSetupActivity = captivePortalSetupActivity;
}
public static void checkForCaptivePortal(URL captivePortalUrl,
CaptivePortalSetupActivity captivePortalSetupActivity, boolean cancelAndRecreateIfRunning) {
if (sTask == null || sTask.getStatus() == Status.FINISHED) {
sTask = new CheckForCaptivePortalTask(captivePortalUrl, captivePortalSetupActivity);
sTask.execute();
} else if (cancelAndRecreateIfRunning) {
sTask.cancel(true);
sTask = new CheckForCaptivePortalTask(captivePortalUrl, captivePortalSetupActivity);
sTask.execute();
}
}
@Override
protected Boolean doInBackground(Void... params) {
if (captivePortalUrl == null) return false;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) captivePortalUrl.openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
urlConnection.getInputStream();
// We got a valid response, but not from the real google
final int responseCode = urlConnection.getResponseCode();
if (responseCode == 408 || responseCode == 504) {
// If we timeout here, we'll try and go through captive portal login
return true;
}
return urlConnection.getResponseCode() != 204;
} catch (IOException e) {
Log.e(TAG, "Captive portal check - probably not a portal: exception "
+ e);
return false;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
@Override
protected void onPostExecute(Boolean isPortal) {
if (isPortal) {
final Context context = captivePortalSetupActivity.getApplicationContext();
responseToken = String.valueOf(new Random().nextLong());
final Intent intent = new Intent(
ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
intent.putExtra(Intent.EXTRA_TEXT, responseToken);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK,
ConnectivityManager.from(context)
.getNetworkForType(ConnectivityManager.TYPE_WIFI));
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
new CaptivePortal(new ICaptivePortal.Stub() {
@Override
public void appResponse(int response) {}
}));
intent.putExtra("status_bar_color",
context.getResources().getColor(R.color.primary_dark));
intent.putExtra("action_bar_color", context.getResources().getColor(
R.color.primary_dark));
intent.putExtra("progress_bar_color", context.getResources().getColor(
R.color.accent));
captivePortalSetupActivity.startSubactivity(intent, REQUEST_CODE_SETUP_CAPTIVE_PORTAL);
} else {
captivePortalSetupActivity.finishAction(RESULT_OK);
captivePortalSetupActivity.finish();
}
}
}
}

View File

@@ -0,0 +1,497 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.util.PhoneMonitor;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.util.List;
public class ChooseDataSimActivity extends BaseSetupWizardActivity {
public static final String TAG = ChooseDataSimActivity.class.getSimpleName();
private ViewGroup mPageView;
private ProgressBar mProgressBar;
private SparseArray<TextView> mNameViews;
private SparseArray<ImageView> mSignalViews;
private SparseArray<CheckBox> mCheckBoxes;
private SparseArray<View> mRows;
private SparseArray<SubscriptionInfo> mSubInfoRecords;
private SparseArray<SignalStrength> mSignalStrengths;
private SparseArray<ServiceState> mServiceStates;
private boolean mIsAttached = false;
private boolean mRadioReady = false;
private PhoneMonitor mPhoneMonitor;
private boolean mDisabledForSwitch = false;
private final Handler mHandler = new Handler();
private final Runnable mRadioReadyRunnable = new Runnable() {
@Override
public void run() {
// If we timeout out waiting for the radio, Oh well.
if (!mRadioReady) {
mRadioReady = true;
checkForRadioReady();
}
}
};
private View.OnClickListener mSetDataSimClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
SubscriptionInfo subInfoRecord = (SubscriptionInfo)view.getTag();
if (subInfoRecord != null) {
changeDataSub(subInfoRecord);
}
}
};
private PhoneMonitor.SubscriptionStateListener mSubscriptionStateListener =
new PhoneMonitor.SubscriptionStateListener() {
@Override
public void onServiceStateChanged(int subId, ServiceState serviceState) {
if (LOGV) {
Log.v(TAG, "onServiceStateChanged{" +
"subId='" + subId + '\'' +
", serviceState=" + serviceState.toString() +
'}');
}
SubscriptionInfo subInfoRecord =
mPhoneMonitor.getActiveSubscriptionInfo(subId);
mRadioReady = SetupWizardUtils.isRadioReady(
ChooseDataSimActivity.this, serviceState);
checkForRadioReady();
mServiceStates.put(subInfoRecord.getSimSlotIndex(), serviceState);
updateSignalStrength(subInfoRecord);
}
@Override
public void onDataConnectionStateChanged(int subId, int state, int networkType) {
if (LOGV) {
Log.v(TAG, "onDataConnectionStateChanged{" +
"subId='" + subId + '\'' +
", state=" + state +
'}');
}
onDefaultDataSubscriptionChanged(subId);
}
@Override
public void onDefaultDataSubscriptionChanged(int subId) {
if (LOGV) {
Log.v(TAG, "onDefaultDataSubscriptionChanged{" +
"subId='" + subId + '\'' +
'}');
}
final int currentDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
if (currentDataSubId != subId) {
updateCurrentDataSub();
hideProgress();
enableViews(true);
}
checkSimChangingState(currentDataSubId, subId);
}
@Override
public void onDefaultDataSubscriptionChangeRequested(int currentSubId,
int newSubId) {
if (LOGV) {
Log.v(TAG, "onDefaultDataSubscriptionChangeRequested{" +
"currentSubId='" + currentSubId + '\'' +
", newSubId=" + newSubId +
'}');
}
checkSimChangingState(currentSubId, newSubId);
}
@Override
public void onSignalStrengthsChanged(int subId, SignalStrength signalStrength) {
if (LOGV) {
Log.v(TAG, "onSignalStrengthsChanged{" +
"subId='" + subId + '\'' +
", signalStrength=" + signalStrength.toString() +
'}');
}
SubscriptionInfo subInfoRecord =
mPhoneMonitor.getActiveSubscriptionInfo(subId);
mSignalStrengths.put(subInfoRecord.getSimSlotIndex(), signalStrength);
updateSignalStrength(subInfoRecord);
}
@Override
public void onSimStateChanged(int subId, int simState) {
if (LOGV) {
Log.v(TAG, "onSimStateChanged{" +
"subId='" + subId + '\'' +
", simState=" + simState +
'}');
}
updateSignalStrengths();
updateCurrentDataSub();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setNextText(R.string.next);
mPhoneMonitor = PhoneMonitor.getInstance();
mPageView = (ViewGroup) findViewById(R.id.page_view);
mProgressBar = (ProgressBar) findViewById(R.id.progress);
List<SubscriptionInfo> subInfoRecords = mPhoneMonitor.getActiveSubscriptionInfoList();
int simCount =
subInfoRecords != null ? subInfoRecords.size() : 0;
mSubInfoRecords = new SparseArray<>(simCount);
for (SubscriptionInfo subInfoRecord : subInfoRecords) {
mSubInfoRecords.put(subInfoRecord.getSimSlotIndex(), subInfoRecord);
updateSignalStrength(subInfoRecord);
}
mNameViews = new SparseArray<>(simCount);
mSignalViews = new SparseArray<>(simCount);
mCheckBoxes = new SparseArray<>(simCount);
mRows = new SparseArray<>(simCount);
mServiceStates = new SparseArray<>(simCount);
mSignalStrengths = new SparseArray<>(simCount);
LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < simCount; i++) {
View simRow = inflater.inflate(R.layout.data_sim_row, null);
mPageView.addView(simRow);
SubscriptionInfo subInfoRecord = mSubInfoRecords.valueAt(i);
simRow.setTag(subInfoRecord);
simRow.setOnClickListener(mSetDataSimClickListener);
int slot = subInfoRecord.getSimSlotIndex();
mNameViews.put(slot, (TextView) simRow.findViewById(R.id.sim_title));
mSignalViews.put(slot, (ImageView) simRow.findViewById(R.id.signal));
mCheckBoxes.put(slot, (CheckBox) simRow.findViewById(R.id.enable_check));
mRows.put(slot, simRow);
mPageView.addView(inflater.inflate(R.layout.divider, null));
}
updateSignalStrengths();
updateCurrentDataSub();
}
@Override
public void onPause() {
super.onPause();
mIsAttached = false;
mPhoneMonitor.removeListener(mSubscriptionStateListener);
}
@Override
public void onResume() {
super.onResume();
mIsAttached = true;
mPhoneMonitor.addListener(mSubscriptionStateListener);
mRadioReady = SetupWizardUtils.isRadioReady(this, null);
updateSignalStrengths();
updateCurrentDataSub();
checkForRadioReady();
if (mRadioReady) {
final int currentDataSub = SubscriptionManager.getDefaultDataSubscriptionId();
checkSimChangingState(currentDataSub, currentDataSub);
}
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
private void checkForRadioReady() {
if (mRadioReady) {
mHandler.removeCallbacks(mRadioReadyRunnable);
showPage();
final int currentDataSub = SubscriptionManager.getDefaultDataSubscriptionId();
checkSimChangingState(currentDataSub, currentDataSub);
return;
} else {
enableViews(false);
showProgress();
if (!mHandler.hasCallbacks(mRadioReadyRunnable)) {
mHandler.postDelayed(mRadioReadyRunnable, SetupWizardApp.RADIO_READY_TIMEOUT);
}
}
}
private void showPage() {
mPageView.setVisibility(View.VISIBLE);
if (!mPageView.isShown()) {
mPageView.startAnimation(
AnimationUtils.loadAnimation(this, R.anim.translucent_enter));
}
}
private void showProgress() {
if (!mProgressBar.isShown()) {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(this, R.anim.translucent_enter));
}
}
private void hideProgress() {
if (mProgressBar.isShown()) {
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(this, R.anim.translucent_exit));
mProgressBar.setVisibility(View.INVISIBLE);
}
}
private void updateSignalStrengths() {
if (mIsAttached) {
for (int i = 0; i < mSubInfoRecords.size(); i++) {
updateSignalStrength(mSubInfoRecords.valueAt(i));
}
}
}
private void changeDataSub(SubscriptionInfo subInfoRecord) {
final int currentDataSub = SubscriptionManager.getDefaultDataSubscriptionId();
final int requestedDataSub = subInfoRecord.getSubscriptionId();
if (LOGV) {
Log.v(TAG, "changeDataSub{" +
"currentDataSub='" + currentDataSub + '\'' +
", requestedDataSub=" + requestedDataSub +
'}');
}
if (currentDataSub != requestedDataSub) {
mPhoneMonitor.changeDataSub(requestedDataSub);
setDataSubChecked(subInfoRecord);
checkSimChangingState(currentDataSub, requestedDataSub);
}
}
private void checkSimChangingState(int currentDataSubId, int changingToDataSubId) {
if (LOGV) {
Log.v(TAG, "checkSimChangingState{" +
"currentDataSubId='" + currentDataSubId + '\'' +
"changingToDataSubId='" + changingToDataSubId + '\'' +
"mIsAttached='" + mIsAttached + '\'' +
", mRadioReady=" + mRadioReady +
'}');
}
if (mIsAttached && mRadioReady) {
if (currentDataSubId != changingToDataSubId) {
showProgress();
enableViews(false);
} else {
hideProgress();
enableViews(true);
}
}
}
private void setDataSubChecked(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
for (int i = 0; i < mCheckBoxes.size(); i++) {
if (subInfoRecord.getSimSlotIndex() == i) {
mCheckBoxes.get(i).setChecked(true);
} else {
mCheckBoxes.get(i).setChecked(false);
}
}
}
}
private void updateCurrentDataSub() {
if (mIsAttached) {
for (int i = 0; i < mSubInfoRecords.size(); i++) {
SubscriptionInfo subInfoRecord = mSubInfoRecords.valueAt(i);
mCheckBoxes.get(i).setChecked(SubscriptionManager.getDefaultDataSubscriptionId()
== subInfoRecord.getSubscriptionId());
if (LOGV) {
Log.v(TAG, "updateCurrentDataSub{" +
"currentDataSubId='" + SubscriptionManager
.getDefaultDataSubscriptionId() + '\'' +
"subInfoRecord.getSubscriptionId()='" +
subInfoRecord.getSubscriptionId() +
'}');
}
}
}
}
private void enableViews(boolean enabled) {
mDisabledForSwitch = !enabled;
enableRows(enabled);
setNextAllowed(enabled);
}
private void enableRows(boolean enabled) {
for (int i = 0; i < mRows.size(); i++) {
final View v = mRows.get(i);
v.setEnabled(enabled);
final SubscriptionInfo subInfoRecord = (SubscriptionInfo)v.getTag();
if (subInfoRecord != null) {
updateCarrierText(subInfoRecord);
}
}
}
private void updateCarrierText(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
String name = mPhoneMonitor.getSimOperatorName(subInfoRecord.getSubscriptionId());
if (TextUtils.isEmpty(name)) {
name = mPhoneMonitor.getNetworkOperatorName(subInfoRecord.getSubscriptionId());
}
ServiceState serviceState = mServiceStates.get(subInfoRecord.getSimSlotIndex());
final int slot = subInfoRecord.getSimSlotIndex();
final View v = mRows.get(slot);
if (TextUtils.isEmpty(name)) {
if (serviceState != null && serviceState.isEmergencyOnly()) {
name = getString(R.string.setup_mobile_data_emergency_only);
} else {
name = getString(R.string.setup_mobile_data_no_service);
}
if (v != null) {
v.setEnabled(false);
}
} else {
if (v != null && !mDisabledForSwitch) {
v.setEnabled(true);
}
}
String formattedName =
getString(R.string.data_sim_name,
slot + 1, name);
mNameViews.get(slot).setText(formattedName);
}
}
private void updateSignalStrength(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
ImageView signalView = mSignalViews.get(subInfoRecord.getSimSlotIndex());
SignalStrength signalStrength = mSignalStrengths.get(subInfoRecord.getSimSlotIndex());
if (LOGV) {
Log.v(TAG, "updateSignalStrength{" +
"signalStrength='" + signalStrength + '\'' +
"signalStrengthLevel='" + ((signalStrength != null) ?
signalStrength.getLevel() : "null") + '\'' +
", subInfoRecord.getSimSlotIndex() =" + subInfoRecord.getSimSlotIndex() +
'}');
}
if (!hasService(subInfoRecord)) {
signalView.setImageResource(R.drawable.ic_signal_no_signal);
} else {
if (signalStrength != null) {
int resId;
switch (signalStrength.getLevel()) {
case 4:
resId = R.drawable.ic_signal_4;
break;
case 3:
resId = R.drawable.ic_signal_3;
break;
case 2:
resId = R.drawable.ic_signal_2;
break;
case 1:
resId = R.drawable.ic_signal_1;
break;
default:
resId = R.drawable.ic_signal_0;
break;
}
signalView.setImageResource(resId);
}
}
updateCarrierText(subInfoRecord);
}
}
private boolean hasService(SubscriptionInfo subInfoRecord) {
boolean retVal;
ServiceState serviceState = mServiceStates.get(subInfoRecord.getSimSlotIndex());
if (serviceState == null) {
serviceState = mPhoneMonitor
.getServiceStateForSubscriber(subInfoRecord.getSubscriptionId());
mServiceStates.put(subInfoRecord.getSimSlotIndex(), serviceState);
}
if (serviceState != null) {
if (LOGV) {
Log.v(TAG, "hasService{" +
"serviceState.getVoiceRegState()='" + serviceState.getVoiceRegState() + '\'' +
"serviceState.getVoiceRegState()='" + serviceState.getVoiceRegState() + '\'' +
", subInfoRecord.getSimSlotIndex() =" + subInfoRecord.getSimSlotIndex() +
'}');
}
// Consider the device to be in service if either voice or data service is available.
// Some SIM cards are marketed as data-only and do not support voice service, and on
// these SIM cards, we want to show signal bars for data service as well as the "no
// service" or "emergency calls only" text that indicates that voice is not available.
switch(serviceState.getVoiceRegState()) {
case ServiceState.STATE_POWER_OFF:
retVal = false;
break;
case ServiceState.STATE_OUT_OF_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
retVal = serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
break;
default:
retVal = true;
}
} else {
retVal = false;
}
return retVal;
}
@Override
protected int getLayoutResId() {
return R.layout.choose_data_sim_page;
}
@Override
protected int getTitleResId() {
return R.string.setup_choose_data_sim;
}
@Override
protected int getIconResId() {
return R.drawable.ic_sim;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,15 +15,12 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.setup;
package com.cyanogenmod.setupwizard;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.TimePickerDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -37,15 +34,12 @@ import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
@@ -57,9 +51,10 @@ import java.util.List;
import java.util.Map;
import java.util.TimeZone;
public class DateTimePage extends SetupPage {
public class DateTimeActivity extends BaseSetupWizardActivity implements
TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
public static final String TAG = "DateTimePage";
public static final String TAG = DateTimeActivity.class.getSimpleName();
private static final String KEY_ID = "id"; // value: String
private static final String KEY_DISPLAYNAME = "name"; // value: String
@@ -69,205 +64,155 @@ public class DateTimePage extends SetupPage {
private static final int HOURS_1 = 60 * 60000;
private TimeZone mCurrentTimeZone;
private View mDateView;
private View mTimeView;
private TextView mDateTextView;
private TextView mTimeTextView;
public DateTimePage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new DateTimeFragment();
fragment.setArguments(args);
private final Handler mHandler = new Handler();
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateTimeAndDateDisplay();
}
return fragment;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setNextText(R.string.next);
final Spinner spinner = (Spinner) findViewById(R.id.timezone_list);
final SimpleAdapter adapter = constructTimezoneAdapter(this, false);
mCurrentTimeZone = TimeZone.getDefault();
mDateView = findViewById(R.id.date_item);
mDateView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showDatePicker();
}
});
mTimeView = findViewById(R.id.time_item);
mTimeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showTimePicker();
}
});
mDateTextView = (TextView)findViewById(R.id.date_text);
mTimeTextView = (TextView)findViewById(R.id.time_text);
// Pre-select current/default timezone
mHandler.post(new Runnable() {
@Override
public void run() {
int tzIndex = getTimeZoneIndex(adapter, mCurrentTimeZone);
spinner.setAdapter(adapter);
if (tzIndex != -1) {
spinner.setSelection(tzIndex);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
final Map<?, ?> map = (Map<?, ?>) adapterView.getItemAtPosition(position);
final String tzId = (String) map.get(KEY_ID);
if (mCurrentTimeZone != null && !mCurrentTimeZone.getID().equals(tzId)) {
// Update the system timezone value
final AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(tzId);
mCurrentTimeZone = TimeZone.getTimeZone(tzId);
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
});
// Pre-select current/default date if epoch
mHandler.post(new Runnable() {
@Override
public void run() {
final Calendar calendar = Calendar.getInstance();
final boolean isEpoch = calendar.get(Calendar.YEAR) == 1970;
if (isEpoch) {
// If epoch, set date to a default date
setDate(DateTimeActivity.this, 2016, Calendar.JANUARY, 1);
}
}
});
}
@Override
public String getKey() {
return TAG;
public void onResume() {
super.onResume();
// Register for time ticks and other reasons for time change
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
registerReceiver(mIntentReceiver, filter, null, null);
updateTimeAndDateDisplay();
}
@Override
public int getTitleResId() {
public void onPause() {
super.onPause();
unregisterReceiver(mIntentReceiver);
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.setup_datetime_page;
}
@Override
protected int getTitleResId() {
return R.string.setup_datetime;
}
@Override
public int getIconResId() {
protected int getIconResId() {
return R.drawable.ic_datetime;
}
public static class DateTimeFragment extends SetupPageFragment
implements TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
setDate(this, year, month, day);
updateTimeAndDateDisplay();
}
private TimeZone mCurrentTimeZone;
private View mDateView;
private View mTimeView;
private TextView mDateTextView;
private TextView mTimeTextView;
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
setTime(this, hourOfDay, minute);
updateTimeAndDateDisplay();
}
private void showDatePicker() {
DatePickerFragment datePickerFragment = DatePickerFragment.newInstance();
datePickerFragment.show(getFragmentManager(), DatePickerFragment.TAG);
}
private final Handler mHandler = new Handler();
@Override
public void onResume() {
super.onResume();
// Register for time ticks and other reasons for time change
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getActivity().registerReceiver(mIntentReceiver, filter, null, null);
updateTimeAndDateDisplay(getActivity());
}
@Override
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mIntentReceiver);
}
@Override
protected void initializePage() {
final Spinner spinner = (Spinner) mRootView.findViewById(R.id.timezone_list);
final SimpleAdapter adapter = constructTimezoneAdapter(getActivity(), false);
mCurrentTimeZone = TimeZone.getDefault();
mDateView = mRootView.findViewById(R.id.date_item);
mDateView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK,
"date_picker");
showDatePicker();
}
});
mTimeView = mRootView.findViewById(R.id.time_item);
mTimeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK,
"time_picker");
showTimePicker();
}
});
mDateTextView = (TextView)mRootView.findViewById(R.id.date_text);
mTimeTextView = (TextView)mRootView.findViewById(R.id.time_text);
// Pre-select current/default timezone
mHandler.post(new Runnable() {
@Override
public void run() {
int tzIndex = getTimeZoneIndex(adapter, mCurrentTimeZone);
spinner.setAdapter(adapter);
if (tzIndex != -1) {
spinner.setSelection(tzIndex);
}
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
final Map<?, ?> map = (Map<?, ?>) adapterView.getItemAtPosition(position);
final String tzId = (String) map.get(KEY_ID);
if (mCurrentTimeZone != null && !mCurrentTimeZone.getID().equals(tzId)) {
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK,
"timezone_picker");
// Update the system timezone value
final Activity activity = getActivity();
final AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(tzId);
mCurrentTimeZone = TimeZone.getTimeZone(tzId);
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.TIMEZONE_CHANGED,
SetupStats.Label.VALUE,
mCurrentTimeZone.getDisplayName());
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
});
// Pre-select current/default date if epoch
mHandler.post(new Runnable() {
@Override
public void run() {
final Calendar calendar = Calendar.getInstance();
final boolean isEpoch = calendar.get(Calendar.YEAR) == 1970;
if (isEpoch) {
// If epoch, set date to a default date
setDate(getActivity(), 2016, Calendar.JANUARY, 1);
}
}
});
}
private void showDatePicker() {
DatePickerFragment datePickerFragment = DatePickerFragment.newInstance();
datePickerFragment.setTargetFragment(this, 0);
datePickerFragment.show(getFragmentManager(), DatePickerFragment.TAG);
}
private void showTimePicker() {
TimePickerFragment timePickerFragment = TimePickerFragment.newInstance();
timePickerFragment.setTargetFragment(this, 0);
timePickerFragment.show(getFragmentManager(), TimePickerFragment.TAG);
}
public void updateTimeAndDateDisplay(Context context) {
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
final Calendar now = Calendar.getInstance();
mTimeTextView.setText(DateFormat.getTimeFormat(getActivity()).format(now.getTime()));
mDateTextView.setText(shortDateFormat.format(now.getTime()));
}
@Override
protected int getLayoutResource() {
return R.layout.setup_datetime_page;
}
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
final Activity activity = getActivity();
if (activity != null) {
setDate(activity, year, month, day);
updateTimeAndDateDisplay(activity);
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.DATE_CHANGED,
SetupStats.Label.VALUE,
month+"/"+day+"/"+year);
}
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
final Activity activity = getActivity();
if (activity != null) {
setTime(activity, hourOfDay, minute);
updateTimeAndDateDisplay(activity);
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.TIME_CHANGED,
SetupStats.Label.VALUE,
hourOfDay+":"+minute);
}
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final Activity activity = getActivity();
if (activity != null) {
updateTimeAndDateDisplay(activity);
}
}
};
private void showTimePicker() {
TimePickerFragment timePickerFragment = TimePickerFragment.newInstance();
timePickerFragment.show(getFragmentManager(), TimePickerFragment.TAG);
}
private void updateTimeAndDateDisplay() {
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(this);
final Calendar now = Calendar.getInstance();
mTimeTextView.setText(DateFormat.getTimeFormat(this).format(now.getTime()));
mDateTextView.setText(shortDateFormat.format(now.getTime()));
}
private static SimpleAdapter constructTimezoneAdapter(Context context,
@@ -289,7 +234,7 @@ public class DateTimePage extends SetupPage {
}
private static List<HashMap<String, Object>> getZones(Context context) {
final List<HashMap<String, Object>> myData = new ArrayList<HashMap<String, Object>>();
final List<HashMap<String, Object>> myData = new ArrayList();
final long date = Calendar.getInstance().getTimeInMillis();
try {
XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones);
@@ -325,7 +270,7 @@ public class DateTimePage extends SetupPage {
private static void addItem(
List<HashMap<String, Object>> myData, String id, String displayName, long date) {
final HashMap<String, Object> map = new HashMap<String, Object>();
final HashMap<String, Object> map = new HashMap();
map.put(KEY_ID, id);
map.put(KEY_DISPLAYNAME, displayName);
final TimeZone tz = TimeZone.getTimeZone(id);
@@ -432,7 +377,8 @@ public class DateTimePage extends SetupPage {
}
}
public static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
public static class TimePickerFragment extends DialogFragment
implements TimePickerDialog.OnTimeSetListener {
private static String TAG = TimePickerFragment.class.getSimpleName();
@@ -443,7 +389,7 @@ public class DateTimePage extends SetupPage {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
((DateTimeFragment) getTargetFragment()).onTimeSet(view, hourOfDay, minute);
((DateTimeActivity)getActivity()).onTimeSet(view, hourOfDay, minute);
}
@Override
@@ -455,12 +401,12 @@ public class DateTimePage extends SetupPage {
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(getActivity()));
}
}
public static class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
public static class DatePickerFragment extends DialogFragment
implements DatePickerDialog.OnDateSetListener {
private static String TAG = DatePickerFragment.class.getSimpleName();
@@ -471,7 +417,7 @@ public class DateTimePage extends SetupPage {
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
((DateTimeFragment) getTargetFragment()).onDateSet(view, year, month, day);
((DateTimeActivity)getActivity()).onDateSet(view, year, month, day);
}
@Override
@@ -483,8 +429,6 @@ public class DateTimePage extends SetupPage {
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_SETUP_FINGERPRINT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_ALLOW_SKIP;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_AUTO_FINISH;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_DETAILS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_FIRST_RUN;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_MATERIAL_LIGHT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_THEME;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_TITLE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_USE_IMMERSIVE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.REQUEST_CODE_SETUP_FINGERPRINT;
import android.content.Intent;
import android.view.View;
public class FingerprintActivity extends SubBaseActivity {
public static final String TAG = FingerprintActivity.class.getSimpleName();
@Override
protected void onStartSubactivity() {
setNextText(R.string.skip);
findViewById(R.id.setup_fingerprint).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchFingerprintSetup();
}
});
}
@Override
protected int getLayoutResId() {
return R.layout.setup_fingerprint;
}
@Override
protected int getTitleResId() {
return R.string.fingerprint_setup_title;
}
@Override
protected int getIconResId() {
return R.drawable.ic_fingerprint;
}
private void launchFingerprintSetup() {
Intent intent = new Intent(ACTION_SETUP_FINGERPRINT);
intent.putExtra(EXTRA_FIRST_RUN, true);
intent.putExtra(EXTRA_ALLOW_SKIP, true);
intent.putExtra(EXTRA_USE_IMMERSIVE, true);
intent.putExtra(EXTRA_THEME, EXTRA_MATERIAL_LIGHT);
intent.putExtra(EXTRA_AUTO_FINISH, false);
/*intent.putExtra(LockPatternUtils.LOCKSCREEN_FINGERPRINT_FALLBACK, true);*/
intent.putExtra(EXTRA_TITLE,
getString(R.string.settings_fingerprint_setup_title));
intent.putExtra(EXTRA_DETAILS,
getString(R.string.settings_fingerprint_setup_details));
startSubactivity(intent, REQUEST_CODE_SETUP_FINGERPRINT);
}
@Override
protected int getSubactivityNextTransition() {
return TRANSITION_ID_SLIDE;
}
}

View File

@@ -15,13 +15,14 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui;
package com.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.DISABLE_NAV_KEYS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_APPLY_DEFAULT_THEME;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_BUTTON_BACKLIGHT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_PRIVACY_GUARD;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_SEND_METRICS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.animation.Animator;
import android.app.Activity;
@@ -33,12 +34,9 @@ import android.content.pm.ActivityInfo;
import android.content.res.ThemeConfig;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
@@ -49,9 +47,6 @@ import android.widget.ProgressBar;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.util.EnableAccessibilityController;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
@@ -79,8 +74,10 @@ public class FinishActivity extends BaseSetupWizardActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (LOGV) {
logActivityState("onCreate savedInstanceState=" + savedInstanceState);
}
mSetupWizardApp = (SetupWizardApp) getApplication();
setContentView(R.layout.finish_activity);
mReveal = (ImageView) findViewById(R.id.reveal);
mFinishingProgressBar = (ProgressBar)findViewById(R.id.finishing_bar);
mEnableAccessibilityController =
@@ -88,27 +85,30 @@ public class FinishActivity extends BaseSetupWizardActivity
setNextText(R.string.start);
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.finish_activity;
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.translucent_enter, R.anim.translucent_exit);
}
@Override
public void onNavigateBack() {
onBackPressed();
}
@Override
public void onNavigateNext() {
applyForwardTransition(TRANSITION_ID_NONE);
startFinishSequence();
}
private void finishSetup() {
if (!mIsFinishing) {
mSetupWizardApp.sendStickyBroadcastAsUser(
new Intent(SetupWizardApp.ACTION_FINISHED),
Binder.getCallingUserHandle());
mIsFinishing = true;
setupRevealImage();
}
@@ -118,7 +118,6 @@ public class FinishActivity extends BaseSetupWizardActivity
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
hideBackButton();
hideNextButton();
mSetupWizardApp.enableCaptivePortalDetection();
Animation fadeIn = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
mFinishingProgressBar.setVisibility(View.VISIBLE);
mFinishingProgressBar.setIndeterminate(true);
@@ -216,7 +215,18 @@ public class FinishActivity extends BaseSetupWizardActivity
if (mEnableAccessibilityController != null) {
mEnableAccessibilityController.onDestroy();
}
new FinishTask(this).execute();
handlePrivacyGuard(mSetupWizardApp);
handleEnableMetrics(mSetupWizardApp);
handleNavKeys(mSetupWizardApp);
final ThemeManager tm = ThemeManager.getInstance(mSetupWizardApp);
tm.unregisterThemeChangeListener(this);
final WallpaperManager wallpaperManager =
WallpaperManager.getInstance(mSetupWizardApp);
wallpaperManager.forgetLoadedWallpaper();
finishAllAppTasks();
Intent intent = WizardManagerHelper.getNextIntent(getIntent(),
Activity.RESULT_OK);
startActivityForResult(intent, NEXT_REQUEST);
}
private static void handleEnableMetrics(SetupWizardApp setupWizardApp) {
@@ -253,11 +263,6 @@ public class FinishActivity extends BaseSetupWizardActivity
private static void handleNavKeys(SetupWizardApp setupWizardApp) {
if (setupWizardApp.getSettingsBundle().containsKey(DISABLE_NAV_KEYS)) {
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.ENABLE_NAV_KEYS,
SetupStats.Label.CHECKED,
String.valueOf(setupWizardApp.getSettingsBundle()
.getBoolean(DISABLE_NAV_KEYS)));
writeDisableNavkeysOption(setupWizardApp,
setupWizardApp.getSettingsBundle().getBoolean(DISABLE_NAV_KEYS));
}
@@ -284,42 +289,4 @@ public class FinishActivity extends BaseSetupWizardActivity
CMSettings.Secure.BUTTON_BRIGHTNESS, oldBright);
}
}
private static class FinishTask extends AsyncTask<Void, Void, Boolean> {
private final FinishActivity mActivity;
public FinishTask(FinishActivity activity) {
mActivity = activity;
}
@Override
protected Boolean doInBackground(Void... params) {
SetupWizardApp app = (SetupWizardApp)mActivity.getApplication();
handlePrivacyGuard(app);
handleEnableMetrics(app);
handleNavKeys(app);
Settings.Global.putInt(mActivity.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(mActivity.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 1);
CMSettings.Secure.putInt(mActivity.getContentResolver(),
CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 1);
final ThemeManager tm = ThemeManager.getInstance(app);
tm.unregisterThemeChangeListener(mActivity);
final WallpaperManager wallpaperManager =
WallpaperManager.getInstance(app);
wallpaperManager.forgetLoadedWallpaper();
SetupWizardUtils.disableSetupWizard(app);
return Boolean.TRUE;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
Intent intent = WizardManagerHelper.getNextIntent(mActivity.getIntent(),
Activity.RESULT_OK);
mActivity.startActivityForResult(intent, 1);
}
}
}

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui;
package com.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.DISABLE_NAV_KEYS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_APPLY_DEFAULT_THEME;
@@ -46,7 +46,6 @@ import android.widget.TextView;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import cyanogenmod.hardware.CMHardwareManager;
@@ -112,12 +111,6 @@ public class LineageSettingsActivity extends BaseSetupWizardActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSetupWizardApp = (SetupWizardApp) getApplication();
setContentView(R.layout.setup_lineage_settings);
TextView title = (TextView) findViewById(android.R.id.title);
title.setText(R.string.setup_services);
ImageView icon = (ImageView) findViewById(R.id.header_icon);
icon.setImageResource(R.drawable.ic_features);
icon.setVisibility(View.VISIBLE);
setNextText(R.string.next);
String privacy_policy = getString(R.string.services_privacy_policy);
String policySummary = getString(R.string.services_explanation, privacy_policy);
@@ -220,6 +213,26 @@ public class LineageSettingsActivity extends BaseSetupWizardActivity {
startActivityForResult(intent, 1);
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.setup_lineage_settings;
}
@Override
protected int getTitleResId() {
return R.string.setup_services;
}
@Override
protected int getIconResId() {
return R.drawable.ic_features;
}
private void updateMetricsOption() {
final Bundle myPageBundle = mSetupWizardApp.getSettingsBundle();
boolean metricsChecked =

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui;
package com.cyanogenmod.setupwizard;
import android.app.Activity;
import android.content.BroadcastReceiver;
@@ -42,7 +42,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.widget.LocalePicker;
import java.util.List;
import java.util.Locale;
@@ -82,12 +82,6 @@ public class LocaleActivity extends BaseSetupWizardActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setup_locale);
TextView title = (TextView) findViewById(android.R.id.title);
title.setText(R.string.setup_locale);
ImageView icon = (ImageView) findViewById(R.id.header_icon);
icon.setImageResource(R.drawable.ic_locale);
icon.setVisibility(View.VISIBLE);
setNextText(R.string.next);
mLanguagePicker = (LocalePicker) findViewById(R.id.locale_list);
loadLanguages();
@@ -116,14 +110,23 @@ public class LocaleActivity extends BaseSetupWizardActivity {
}
@Override
public void onNavigateBack() {
onBackPressed();
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
public void onNavigateNext() {
Intent intent = WizardManagerHelper.getNextIntent(getIntent(), Activity.RESULT_OK);
startActivityForResult(intent, 1);
protected int getLayoutResId() {
return R.layout.setup_locale;
}
@Override
protected int getTitleResId() {
return R.string.setup_locale;
}
@Override
protected int getIconResId() {
return R.drawable.ic_locale;
}
private void loadLanguages() {

View File

@@ -0,0 +1,219 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class LocationSettingsActivity extends BaseSetupWizardActivity {
public static final String TAG =
LocationSettingsActivity.class.getSimpleName().substring(0, 22);
private View mLocationRow;
private View mBatteryRow;
private View mNetworkRow;
private CheckBox mNetwork;
private CheckBox mBattery;
private CheckBox mLocationAccess;
private ContentResolver mContentResolver;
/** Broadcast intent action when the location mode is about to change. */
private static final String MODE_CHANGING_ACTION =
"com.android.settings.location.MODE_CHANGING";
private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
private static final String NEW_MODE_KEY = "NEW_MODE";
private int mCurrentMode = Settings.Secure.LOCATION_MODE_OFF;
private View.OnClickListener mLocationClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleLocationAccess(!mLocationAccess.isChecked());
}
};
private View.OnClickListener mBatteryClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleBatterySaving(!mBattery.isChecked());
}
};
private View.OnClickListener mNetworkClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleNetwork(!mNetwork.isChecked());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setNextText(R.string.next);
mContentResolver = getContentResolver();
TextView summaryView = (TextView) findViewById(android.R.id.summary);
summaryView.setText(R.string.location_services_summary);
mLocationRow = findViewById(R.id.location);
mLocationRow.setOnClickListener(mLocationClickListener);
mLocationAccess = (CheckBox) findViewById(R.id.location_checkbox);
mBatteryRow = findViewById(R.id.battery_saving);
mBatteryRow.setOnClickListener(mBatteryClickListener);
mBattery = (CheckBox) findViewById(R.id.battery_saving_checkbox);
mNetworkRow = findViewById(R.id.network);
mNetworkRow.setOnClickListener(mNetworkClickListener);
mNetwork = (CheckBox) findViewById(R.id.network_checkbox);
TextView networkSummary = (TextView) findViewById(R.id.network_summary);
final boolean hasTelephony = SetupWizardUtils.hasTelephony(this);
if (hasTelephony) {
networkSummary.setText(R.string.location_network_telephony);
} else {
networkSummary.setText(R.string.location_network);
}
}
@Override
public void onResume() {
super.onResume();
refreshLocationMode();
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.location_settings;
}
@Override
protected int getTitleResId() {
return R.string.setup_location;
}
@Override
protected int getIconResId() {
return R.drawable.ic_location;
}
private void setLocationMode(int mode) {
Intent intent = new Intent(MODE_CHANGING_ACTION);
intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
intent.putExtra(NEW_MODE_KEY, mode);
sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
Settings.Secure.putInt(mContentResolver, Settings.Secure.LOCATION_MODE, mode);
refreshLocationMode();
}
private void refreshLocationMode() {
int mode = Settings.Secure.getInt(mContentResolver, Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
if (mCurrentMode != mode) {
mCurrentMode = mode;
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Location mode has been changed");
}
updateLocationToggles(mode);
}
}
private void updateLocationToggles(int mode) {
switch (mode) {
case Settings.Secure.LOCATION_MODE_OFF:
mLocationAccess.setChecked(false);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
mLocationAccess.setChecked(true);
mBattery.setChecked(false);
mBattery.setEnabled(true);
mBatteryRow.setEnabled(true);
mNetwork.setChecked(false);
mNetwork.setEnabled(true);
mNetworkRow.setEnabled(true);
break;
case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
mLocationAccess.setChecked(true);
mBattery.setChecked(true);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
mLocationAccess.setChecked(true);
mNetwork.setChecked(true);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
break;
default:
mLocationAccess.setChecked(false);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
}
}
private void onToggleLocationAccess(boolean checked) {
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
}
}
private void onToggleBatterySaving(boolean checked) {
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
}
}
private void onToggleNetwork(boolean checked) {
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
}
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.util.NetworkMonitor;
import com.cyanogenmod.setupwizard.util.PhoneMonitor;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class MobileDataActivity extends BaseSetupWizardActivity {
public static final String TAG = MobileDataActivity.class.getSimpleName();
private static final int DC_READY_TIMEOUT = 20 * 1000;
private ProgressBar mProgressBar;
private View mEnableDataRow;
private Switch mEnableMobileData;
private ImageView mSignalView;
private TextView mNameView;
private TelephonyManager mPhone;
private SignalStrength mSignalStrength;
private ServiceState mServiceState;
private PhoneMonitor mPhoneMonitor;
private NetworkMonitor mNetworkMonitor;
private boolean mIsAttached = false;
private final Handler mHandler = new Handler();
private final Runnable mRadioReadyRunnable = new Runnable() {
@Override
public void run() {
hideWaitForRadio();
}
};
private final Runnable mDataConnectionReadyRunnable = new Runnable() {
@Override
public void run() {
onDataStateReady();
}
};
private PhoneMonitor.SubscriptionStateListener mSubscriptionStateListener =
new PhoneMonitor.SubscriptionStateListener() {
@Override
public void onServiceStateChanged(int subId, ServiceState serviceState) {
if (LOGV) {
Log.v(TAG, "onServiceStateChanged{" +
"subId='" + subId + '\'' +
", serviceState=" + serviceState.toString() +
'}');
}
if (SetupWizardUtils.isRadioReady(MobileDataActivity.this, serviceState)) {
hideWaitForRadio();
}
mServiceState = serviceState;
updateSignalStrength();
}
@Override
public void onDataConnectionStateChanged(int subId, int state, int networkType) {
if (LOGV) {
Log.v(TAG, "onDataConnectionStateChanged{" +
"subId='" + subId + '\'' +
", state=" + state +
'}');
}
if (state == TelephonyManager.DATA_CONNECTED) {
onDataStateReady();
}
}
@Override
public void onDefaultDataSubscriptionChanged(int subId) {}
@Override
public void onDefaultDataSubscriptionChangeRequested(int currentSubId,
int newSubId) {}
@Override
public void onSignalStrengthsChanged(int subId, SignalStrength signalStrength) {
if (LOGV) {
Log.v(TAG, "onSignalStrengthsChanged{" +
"subId='" + subId + '\'' +
", signalStrength=" + signalStrength.toString() +
'}');
}
mSignalStrength = signalStrength;
updateSignalStrength();
}
@Override
public void onSimStateChanged(int subId, int simState) {
if (LOGV) {
Log.v(TAG, "onSimStateChanged{" +
"subId='" + subId + '\'' +
", simState=" + simState +
'}');
}
}
};
private View.OnClickListener mEnableDataClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean checked = !mEnableMobileData.isChecked();
SetupWizardUtils.setMobileDataEnabled(MobileDataActivity.this, checked);
mEnableMobileData.setChecked(checked);
if (checked && !mNetworkMonitor.isWifiConnected()) {
waitForData();
} else {
onDataStateReady();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPhoneMonitor = PhoneMonitor.getInstance();
mNetworkMonitor = NetworkMonitor.getInstance();
setNextText(R.string.next);
mProgressBar = (ProgressBar) findViewById(R.id.progress);
mEnableDataRow = findViewById(R.id.data);
mEnableDataRow.setOnClickListener(mEnableDataClickListener);
mEnableMobileData = (Switch) findViewById(R.id.data_switch);
mSignalView = (ImageView) findViewById(R.id.signal);
mNameView = (TextView) findViewById(R.id.enable_data_title);
updateDataConnectionStatus();
updateSignalStrength();
}
@Override
public void onResume() {
super.onResume();
mIsAttached = true;
mPhone = getSystemService(TelephonyManager.class);
mPhoneMonitor.addListener(mSubscriptionStateListener);
updateDataConnectionStatus();
updateSignalStrength();
if (SetupWizardUtils.isRadioReady(this, null)) {
hideWaitForRadio();
} else {
mHandler.postDelayed(mRadioReadyRunnable, SetupWizardApp.RADIO_READY_TIMEOUT);
}
}
@Override
public void onPause() {
super.onPause();
mIsAttached = false;
mPhoneMonitor.removeListener(mSubscriptionStateListener);
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
private void hideWaitForRadio() {
if (mProgressBar.isShown()) {
mHandler.removeCallbacks(mRadioReadyRunnable);
// Something else, like data enablement, may have grabbed
// the "hold" status. Kill it only if "Next" is active
if (isNextAllowed()) {
mProgressBar.setVisibility(View.INVISIBLE);
}
}
}
private void waitForData() {
if (!mProgressBar.isShown()) {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(this, R.anim.translucent_enter));
mEnableDataRow.setEnabled(false);
setNextAllowed(false);
mHandler.postDelayed(mDataConnectionReadyRunnable, DC_READY_TIMEOUT);
}
}
private void onDataStateReady() {
mHandler.removeCallbacks(mDataConnectionReadyRunnable);
if ((mProgressBar.isShown()) ||
!isNextAllowed()) {
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(this, R.anim.translucent_exit));
mProgressBar.setVisibility(View.INVISIBLE);
mEnableDataRow.setEnabled(true);
setNextAllowed(true);
}
}
private void updateCarrierText() {
if (mIsAttached) {
String name = mPhone.getSimOperatorName(SubscriptionManager.getDefaultSubscriptionId());
if (TextUtils.isEmpty(name)) {
name = mPhone.getNetworkOperatorName(SubscriptionManager.getDefaultSubscriptionId());
}
if (TextUtils.isEmpty(name)) {
if (mServiceState != null && mServiceState.isEmergencyOnly()) {
name = getString(R.string.setup_mobile_data_emergency_only);
} else {
name = getString(R.string.setup_mobile_data_no_service);
}
}
mNameView.setText(name);
}
}
private void updateSignalStrength() {
if (mIsAttached) {
if (LOGV) {
Log.v(TAG, "updateSignalStrength{" +
"signalStrength='" + mSignalStrength + '\'' +
"signalStrengthLevel='" + ((mSignalStrength != null) ?
mSignalStrength.getLevel() : "null") + '\'' +
'}');
}
if (!hasService()) {
mSignalView.setImageResource(R.drawable.ic_signal_no_signal);
} else {
if (mSignalStrength != null) {
int resId;
switch (mSignalStrength.getLevel()) {
case 4:
resId = R.drawable.ic_signal_4;
break;
case 3:
resId = R.drawable.ic_signal_3;
break;
case 2:
resId = R.drawable.ic_signal_2;
break;
case 1:
resId = R.drawable.ic_signal_1;
break;
default:
resId = R.drawable.ic_signal_0;
break;
}
mSignalView.setImageResource(resId);
}
}
updateCarrierText();
}
}
private void updateDataConnectionStatus() {
mEnableMobileData.setChecked(SetupWizardUtils.isMobileDataEnabled(this));
}
private boolean hasService() {
boolean retVal;
if (mServiceState == null) {
mServiceState = TelephonyManager.from(this)
.getServiceStateForSubscriber(SubscriptionManager.getDefaultSubscriptionId());
}
if (mServiceState != null) {
// Consider the device to be in service if either voice or data service is available.
// Some SIM cards are marketed as data-only and do not support voice service, and on
// these SIM cards, we want to show signal bars for data service as well as the "no
// service" or "emergency calls only" text that indicates that voice is not available.
switch(mServiceState.getVoiceRegState()) {
case ServiceState.STATE_POWER_OFF:
retVal = false;
break;
case ServiceState.STATE_OUT_OF_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
break;
default:
retVal = true;
}
} else {
retVal = false;
}
return retVal;
}
@Override
protected int getLayoutResId() {
return R.layout.mobile_data_settings;
}
@Override
protected int getTitleResId() {
return R.string.setup_mobile_data;
}
@Override
protected int getIconResId() {
return R.drawable.ic_mobile_data;
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_SETUP_LOCKSCREEN;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_DETAILS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_TITLE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.REQUEST_CODE_SETUP_LOCKSCREEN;
import android.content.Intent;
import android.view.View;
public class ScreenLockActivity extends SubBaseActivity {
public static final String TAG = ScreenLockActivity.class.getSimpleName();
@Override
protected void onStartSubactivity() {
setNextText(R.string.skip);
findViewById(R.id.setup_lockscreen).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchLockscreenSetup();
}
});
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.setup_lockscreen;
}
@Override
protected int getTitleResId() {
return R.string.lockscreen_setup_title;
}
@Override
protected int getIconResId() {
return R.drawable.ic_lock_screen;
}
private void launchLockscreenSetup() {
Intent intent = new Intent(ACTION_SETUP_LOCKSCREEN);
intent.putExtra(EXTRA_TITLE,
getString(R.string.settings_lockscreen_setup_title));
intent.putExtra(EXTRA_DETAILS,
getString(R.string.settings_lockscreen_setup_details));
intent.putExtra(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
startSubactivity(intent, REQUEST_CODE_SETUP_LOCKSCREEN);
}
@Override
protected int getSubactivityNextTransition() {
return TRANSITION_ID_SLIDE;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_LOAD;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_SCRIPT_URI;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import com.cyanogenmod.setupwizard.wizardmanager.WizardManager;
public class SetupWizardActivity extends BaseSetupWizardActivity {
private static final String TAG = SetupWizardActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (LOGV) {
Log.v(TAG, "onCreate savedInstanceState=" + savedInstanceState);
}
if (SetupWizardUtils.hasGMS(this)) {
if (LOGV) {
Log.v(TAG, "Has GMS disabling local wizard manager");
}
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
SetupWizardUtils.disableComponentsForGMS(this);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else {
onSetupStart();
SetupWizardUtils.resetComponent(this, WizardManager.class);
Intent intent = new Intent(ACTION_LOAD);
if (isPrimaryUser()) {
intent.putExtra(EXTRA_SCRIPT_URI, getString(R.string.cm_wizard_script_uri));
} else {
intent.putExtra(EXTRA_SCRIPT_URI, getString(R.string.cm_wizard_script_user_uri));
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
finish();
}
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,31 +22,42 @@ import android.app.Application;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import com.cyanogenmod.setupwizard.util.NetworkMonitor;
import com.cyanogenmod.setupwizard.util.PhoneMonitor;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import com.cyanogenmod.setupwizard.wizardmanager.WizardManager;
public class SetupWizardApp extends Application {
public static final String TAG = SetupWizardApp.class.getSimpleName();
// Leave this off for release
public static final boolean DEBUG = false;
/* Verbose Logging */
public static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
public static final String ACTION_FINISHED = "com.cyanogenmod.setupwizard.SETUP_FINISHED";
public static final String ACTION_SETUP_WIFI = "com.android.net.wifi.SETUP_WIFI_NETWORK";
public static final String ACTION_SETUP_FINGERPRINT = "android.settings.FINGERPRINT_SETUP";
public static final String ACTION_SETUP_LOCKSCREEN = "com.android.settings.SETUP_LOCK_SCREEN";
public static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
public static final String ACTION_NEXT = "com.android.wizard.NEXT";
public static final String ACTION_LOAD = "com.android.wizard.LOAD";
public static final String EXTRA_FIRST_RUN = "firstRun";
public static final String EXTRA_ALLOW_SKIP = "allowSkip";
public static final String EXTRA_AUTO_FINISH = "wifi_auto_finish_on_connect";
public static final String EXTRA_USE_IMMERSIVE = "useImmersiveMode";
public static final String EXTRA_HAS_MULTIPLE_USERS = "hasMultipleUsers";
public static final String EXTRA_THEME = "theme";
public static final String EXTRA_MATERIAL_LIGHT = "material_light";
public static final String EXTRA_TITLE = "title";
public static final String EXTRA_DETAILS = "details";
public static final String EXTRA_SCRIPT_URI = "scriptUri";
public static final String EXTRA_ACTION_ID = "actionId";
public static final String EXTRA_RESULT_CODE = "com.android.setupwizard.ResultCode";
public static final String KEY_DETECT_CAPTIVE_PORTAL = "captive_portal_detection_enabled";
public static final String KEY_SEND_METRICS = "send_metrics";
@@ -64,14 +76,12 @@ public class SetupWizardApp extends Application {
public static final int REQUEST_CODE_SETUP_WIFI = 0;
public static final int REQUEST_CODE_SETUP_CAPTIVE_PORTAL= 4;
public static final int REQUEST_CODE_SETUP_BLUETOOTH= 5;
public static final int REQUEST_CODE_UNLOCK = 6;
public static final int REQUEST_CODE_SETUP_FINGERPRINT = 7;
public static final int REQUEST_CODE_SETUP_LOCKSCREEN = 9;
public static final int RADIO_READY_TIMEOUT = 10 * 1000;
private boolean mIsRadioReady = false;
private boolean mIsAuthorized = false;
private boolean mIgnoreSimLocale = false;
private final Bundle mSettingsBundle = new Bundle();
@@ -87,18 +97,16 @@ public class SetupWizardApp extends Application {
@Override
public void onCreate() {
super.onCreate();
if (LOGV) {
Log.v(TAG, "onCreate()");
}
NetworkMonitor.initInstance(this);
PhoneMonitor.initInstance(this);
final boolean isOwner = SetupWizardUtils.isOwner();
if (!isOwner) {
Thread t = new Thread(){
@Override
public void run() {
disableThemeComponentsForSecondaryUser();
}
};
t.run();
} else {
disableCaptivePortalDetection();
disableThemeComponentsForSecondaryUser();
}
SetupWizardUtils.disableComponentsForMissingFeatures(this);
mHandler.postDelayed(mRadioTimeoutRunnable, SetupWizardApp.RADIO_READY_TIMEOUT);
}
@@ -113,14 +121,6 @@ public class SetupWizardApp extends Application {
mIsRadioReady = radioReady;
}
public boolean isAuthorized() {
return mIsAuthorized;
}
public void setIsAuthorized(boolean isAuthorized) {
mIsAuthorized = isAuthorized;
}
public boolean ignoreSimLocale() {
return mIgnoreSimLocale;
}
@@ -133,14 +133,6 @@ public class SetupWizardApp extends Application {
return mSettingsBundle;
}
public void disableCaptivePortalDetection() {
Settings.Global.putInt(getContentResolver(), KEY_DETECT_CAPTIVE_PORTAL, 0);
}
public void enableCaptivePortalDetection() {
Settings.Global.putInt(getContentResolver(), KEY_DETECT_CAPTIVE_PORTAL, 1);
}
private void disableThemeComponentsForSecondaryUser() {
PackageManager pm = getPackageManager();
for(String pkgName : THEME_PACKAGES) {

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.android.setupwizardlib.util.SystemBarHelper;
import com.cyanogenmod.setupwizard.util.PhoneMonitor;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class SetupWizardExitActivity extends BaseSetupWizardActivity {
private static final String TAG = SetupWizardExitActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (LOGV) {
Log.v(TAG, "onCreate savedInstanceState=" + savedInstanceState);
}
SystemBarHelper.showSystemBars(getWindow(), this);
SetupWizardUtils.enableStatusBar(this);
SetupWizardUtils.enableCaptivePortalDetection(this);
PhoneMonitor.onSetupFinished();
launchHome();
finish();
applyForwardTransition(TRANSITION_ID_FADE);
Intent i = new Intent();
i.setClassName(getPackageName(), SetupWizardExitService.class.getName());
startService(i);
}
private void launchHome() {
startActivity(new Intent("android.intent.action.MAIN")
.addCategory("android.intent.category.HOME")
.addFlags(FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_CLEAR_TASK));
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.annotation.Nullable;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class SetupWizardExitService extends IntentService {
private static final String TAG = "SUWExitService";
public SetupWizardExitService() {
super(TAG);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if (LOGV) {
Log.v(TAG, "onHandleIntent intent=" + intent.toString());
}
SetupWizardUtils.finishSetupWizard(this);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.content.pm.PackageManager.GET_RECEIVERS;
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.app.Activity;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.util.List;
public class SetupWizardTestActivity extends Activity {
private static final String TAG = SetupWizardTestActivity.class.getSimpleName();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (LOGV) {
Log.v(TAG, "onCreate savedInstanceState=" + savedInstanceState);
}
if (SetupWizardUtils.isOwner()) {
Settings.Global.putInt(getContentResolver(), "device_provisioned", 0);
}
Settings.Secure.putInt(getContentResolver(), "user_setup_complete", 0);
SetupWizardUtils.resetComponentSets(this, GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES | MATCH_DISABLED_COMPONENTS);
forgetAllWifi();
Intent setupIntent = new Intent("android.intent.action.MAIN")
.addCategory("android.intent.category.HOME")
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
SetupWizardUtils.disableComponentsForMissingFeatures(this);
startActivity(setupIntent);
finish();
}
private void forgetAllWifi() {
WifiManager wm = getSystemService(WifiManager.class);
if (wm != null) {
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs) {
wm.forget(config.networkId, null);
}
}
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import android.os.Bundle;
import android.widget.ImageView;
import com.android.setupwizardlib.util.ResultCodes;
import com.cyanogenmod.setupwizard.util.PhoneMonitor;
public class SimMissingActivity extends BaseSetupWizardActivity {
public static final String TAG = SimMissingActivity.class.getSimpleName();
private static final int SIM_DEFAULT = 0;
private static final int SIM_SIDE = 1;
private static final int SIM_BACK = 2;
private PhoneMonitor mPhoneMonitor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPhoneMonitor = PhoneMonitor.getInstance();
if (!mPhoneMonitor.simMissing()) {
finishAction(RESULT_OK);
}
setNextText(R.string.skip);
final int simLocation = getResources().getInteger(
R.integer.sim_image_type);
ImageView simLogo = ((ImageView)findViewById(R.id.sim_slot_image));
switch (simLocation) {
case SIM_SIDE:
simLogo.setImageResource(R.drawable.sim_side);
break;
case SIM_BACK:
simLogo.setImageResource(R.drawable.sim_back);
break;
default:
simLogo.setImageResource(R.drawable.sim);
simLogo.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
}
}
@Override
public void onNavigateNext() {
if (mPhoneMonitor.simMissing()) {
nextAction(ResultCodes.RESULT_SKIP);
} else {
super.onNavigateNext();
}
}
@Override
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.sim_missing_page;
}
@Override
protected int getTitleResId() {
return R.string.setup_sim_missing;
}
@Override
protected int getIconResId() {
return R.drawable.ic_sim;
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static android.content.Intent.FLAG_ACTIVITY_FORWARD_RESULT;
import static com.android.setupwizardlib.util.ResultCodes.RESULT_ACTIVITY_NOT_FOUND;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_ACTION_ID;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_SCRIPT_URI;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.annotation.NonNull;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public abstract class SubBaseActivity extends BaseSetupWizardActivity {
public static final String TAG = SubBaseActivity.class.getSimpleName();
private boolean mIsSubactivityNotFound = false;
private int mRequestCode;
protected abstract void onStartSubactivity();
@Override
protected void onCreate(Bundle savedInstanceState) {
if (LOGV) {
Log.d(TAG, "onCreate savedInstanceState=" + savedInstanceState);
}
super.onCreate(savedInstanceState);
setNextText(R.string.skip);
if (savedInstanceState == null) {
onStartSubactivity();
}
setNextAllowed(false);
}
@Override
public void onStart() {
super.onStart();
mIsActivityVisible = true;
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putInt("request_code", mRequestCode);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mRequestCode = savedInstanceState.getInt("request_code");
}
protected void startSubactivity(Intent subactivityIntent, int requestCode) {
mRequestCode = requestCode;
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_SCRIPT_URI)) {
subactivityIntent.putExtra(EXTRA_SCRIPT_URI, intent.getStringExtra(EXTRA_SCRIPT_URI));
subactivityIntent.putExtra(EXTRA_ACTION_ID, intent.getStringExtra(EXTRA_ACTION_ID));
}
boolean activityForwardsResult =
(subactivityIntent.getFlags() & FLAG_ACTIVITY_FORWARD_RESULT) != 0;
if (activityForwardsResult) {
try {
startFirstRunActivity(subactivityIntent);
setResultCode(RESULT_OK);
finish();
} catch (ActivityNotFoundException e) {
Log.w(TAG, "activity not found; start next screen and finish; intent="
+ intent);
mIsSubactivityNotFound = true;
nextAction(RESULT_ACTIVITY_NOT_FOUND);
finish();
return;
}
}
startFirstRunActivityForResult(subactivityIntent, requestCode);
mIsSubactivityNotFound = false;
applyForwardTransition(getSubactivityPreviousTransition());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Bundle extras = null;
if (LOGV) {
Log.v(TAG, "onActivityResult(" + getRequestName(requestCode) +
", " + getResultName(requestCode, resultCode));
}
if (requestCode == mRequestCode) {
StringBuilder append = new StringBuilder().append("subactivity result {")
.append(getRequestName(requestCode)).append(", ")
.append(getResultName(mRequestCode, resultCode)).append(", ");
if (data != null) {
extras = data.getExtras();
}
Log.i(TAG, append.append(extras).append("}").toString());
onSubactivityResult(requestCode, resultCode, data);
} else if (resultCode == RESULT_CANCELED) {
onStartSubactivity();
mIsGoingBack = true;
applyBackwardTransition(getSubactivityNextTransition());
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
protected void onSubactivityResult(int requestCode, int resultCode, Intent data) {
if (LOGV) {
StringBuilder append = new StringBuilder().append("onSubactivityResult(")
.append(getRequestName(requestCode)).append(", ")
.append(getResultName(requestCode, resultCode)).append(", ");
Bundle extras = null;
if (data != null) {
extras = data.getExtras();
}
Log.v(TAG, append.append(extras).append(")").toString());
}
if (resultCode != RESULT_CANCELED) {
applyForwardTransition(getSubactivityNextTransition());
nextAction(resultCode, data);
} else if (mIsSubactivityNotFound) {
nextAction(RESULT_ACTIVITY_NOT_FOUND);
finish();
} else {
applyBackwardTransition(getSubactivityPreviousTransition());
finishAction(RESULT_CANCELED, data);
}
}
protected int getSubactivityPreviousTransition() {
return TRANSITION_ID_DEFAULT;
}
protected int getSubactivityNextTransition() {
return TRANSITION_ID_DEFAULT;
}
@Override
protected int getTransition() {
return TRANSITION_ID_FADE;
}
@Override
protected int getLayoutResId() {
return R.layout.setup_loading_page;
}
@Override
protected int getTitleResId() {
return R.string.loading;
}
}

View File

@@ -15,33 +15,24 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui;
package com.cyanogenmod.setupwizard;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.util.EnableAccessibilityController;
public class WelcomeActivity extends BaseSetupWizardActivity {
public static final String TAG = WelcomeActivity.class.getSimpleName();
private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
private View mRootView;
private EnableAccessibilityController mEnableAccessibilityController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_activity);
mRootView = findViewById(R.id.root);
setNextText(R.string.next);
setBackText(R.string.emergency_call);
@@ -58,26 +49,21 @@ public class WelcomeActivity extends BaseSetupWizardActivity {
});
}
@Override
public void onBackPressed() {}
@Override
public void onNavigateBack() {
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
ActivityOptions options =
ActivityOptions.makeCustomAnimation(this,
android.R.anim.fade_in,
android.R.anim.fade_out);
startActivity(intent, options.toBundle());
startEmergencyDialer();
}
@Override
public void onNavigateNext() {
ActivityOptions options =
ActivityOptions.makeCustomAnimation(this,
R.anim.slide_left,
0);
Intent intent = WizardManagerHelper.getNextIntent(getIntent(), Activity.RESULT_OK);
startActivityForResult(intent, 1, options.toBundle());
protected int getTransition() {
return TRANSITION_ID_SLIDE;
}
@Override
protected int getLayoutResId() {
return R.layout.welcome_activity;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_SETUP_WIFI;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_MATERIAL_LIGHT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.REQUEST_CODE_SETUP_WIFI;
import android.content.Intent;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class WifiSetupActivity extends SubBaseActivity {
public static final String TAG = WifiSetupActivity.class.getSimpleName();
@Override
protected void onStartSubactivity() {
tryEnablingWifi();
Intent intent = new Intent(ACTION_SETUP_WIFI);
if (SetupWizardUtils.hasLeanback(this)) {
intent.setComponent(SetupWizardUtils.mTvwifisettingsActivity);
}
intent.putExtra(SetupWizardApp.EXTRA_FIRST_RUN, true);
intent.putExtra(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
intent.putExtra(SetupWizardApp.EXTRA_USE_IMMERSIVE, true);
intent.putExtra(SetupWizardApp.EXTRA_THEME, EXTRA_MATERIAL_LIGHT);
intent.putExtra(SetupWizardApp.EXTRA_AUTO_FINISH, false);
startSubactivity(intent, REQUEST_CODE_SETUP_WIFI);
}
@Override
protected int getSubactivityNextTransition() {
return TRANSITION_ID_SLIDE;
}
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod 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.cyanogenmod.setupwizard.cmstats;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.util.Log;
import java.util.LinkedList;
public class SetupStats {
private static final String TAG = SetupStats.class.getSimpleName();
private static final String ANALYTIC_INTENT = "com.cyngn.stats.action.SEND_ANALYTIC_EVENT";
private static final String ANALYTIC_PERMISSION = "com.cyngn.stats.SEND_ANALYTICS";
public static final String TRACKING_ID = "tracking_id";
private final LinkedList<Event> mEvents = new LinkedList<Event>();
private static final SetupStats sInstance = new SetupStats();
private static final boolean DEBUG = false;
private SetupStats() {}
public static void addEvent(String category, String action,
String label, String value) {
sInstance.mEvents.add(new Event(category, action, label, value));
}
public static void addEvent(String category, String action) {
sInstance.mEvents.add(new Event(category, action, null, null));
}
public static void sendEvents(Context context) {
while (!sInstance.mEvents.isEmpty()) {
sInstance.sendEvent(context, sInstance.mEvents.remove());
}
}
private void sendEvent(Context context, Event event) {
if (!StatsUtils.isStatsPackageInstalled(context)
|| !StatsUtils.isStatsCollectionEnabled(context)) {
return;
}
// Create new intent
Intent intent = new Intent();
intent.setAction(ANALYTIC_INTENT);
// add tracking id
intent.putExtra(TRACKING_ID, context.getPackageName());
// append
intent.putExtra(Fields.EVENT_CATEGORY, event.category);
if (DEBUG) Log.d(TAG, Fields.EVENT_CATEGORY + "=" + event.category);
intent.putExtra(Fields.EVENT_ACTION, event.action);
if (DEBUG) Log.d(TAG, Fields.EVENT_ACTION + "=" + event.action);
// check if exist
if (event.label != null) {
intent.putExtra(Fields.EVENT_LABEL, event.label);
if (DEBUG) Log.d(TAG, Fields.EVENT_LABEL + "=" + event.label);
}
if (event.value != null) {
intent.putExtra(Fields.EVENT_VALUE, event.value);
if (DEBUG) Log.d(TAG, Fields.EVENT_VALUE + "=" + event.value);
}
// broadcast for internal package
context.sendBroadcastAsUser(intent,
new UserHandle(UserHandle.USER_CURRENT), ANALYTIC_PERMISSION);
}
private static final class Event {
private final String category;
private final String action;
private final String label;
private final String value;
public Event(String category, String action, String label, String value) {
this.action = action;
this.category = category;
this.label = label;
this.value = value;
}
}
public static final class Fields {
public static final String EVENT_CATEGORY = "category";
public static final String EVENT_ACTION = "action";
public static final String EVENT_LABEL = "label";
public static final String EVENT_VALUE = "value";
}
public static final class Categories {
public static final String APP_LAUNCH = "app_launch";
public static final String APP_FINISHED = "app_finish";
public static final String PAGE_LOAD = "page_load";
public static final String EXTERNAL_PAGE_LOAD = "external_page_load";
public static final String BUTTON_CLICK = "button_click";
public static final String SETTING_CHANGED = "setting_changed";
}
public static final class Action {
public static final String PAGE_LOADED = "page_loaded";
public static final String PREVIOUS_BUTTON = "previous_button";
public static final String NEXT_BUTTON = "next_button";
public static final String CHANGE_LOCALE = "change_local";
public static final String EXTERNAL_PAGE_LAUNCH = "external_page_launch";
public static final String EXTERNAL_PAGE_RESULT = "external_page_result";
public static final String ENABLE_MOBILE_DATA = "enable_mobile_data";
public static final String PREFERRED_DATA_SIM = "preferred_data_sim";
public static final String APPLY_CUSTOM_THEME = "apply_custom_theme";
public static final String USE_SECURE_SMS = "use_secure_sms";
public static final String ENABLE_BACKUP = "enable_backup";
public static final String ENABLE_NAV_KEYS = "enable_nav_keys";
public static final String ENABLE_LOCATION = "enable_location";
public static final String ENABLE_NETWORK_LOCATION = "enable_network_location";
public static final String ENABLE_GPS_LOCATION = "enable_gps_location";
public static final String DATE_CHANGED = "date_changed";
public static final String TIME_CHANGED = "time_changed";
public static final String TIMEZONE_CHANGED = "timezone_changed";
}
public static final class Label {
public static final String PAGE = "page";
public static final String LOCALE = "local";
public static final String RESULT = "result";
public static final String WIFI_SETUP = "wifi_setup";
public static final String BLUETOOTH_SETUP = "bluetooth_setup";
public static final String CYANOGEN_ACCOUNT = "cyanogen_account_setup";
public static final String CAPTIVE_PORTAL_LOGIN = "captive_portal_login";
public static final String EMERGENCY_CALL = "emergency_call";
public static final String GMS_ACCOUNT = "gms_account";
public static final String RESTORE = "restore";
public static final String CHECKED = "checked";
public static final String VALUE = "value";
public static final String SLOT = "slot";
public static final String TOTAL_TIME = "total_time";
public static final String FINGERPRINT_SETUP = "fingerprint_setup";
public static final String LOCKSCREEN_SETUP = "lockscreen_setup";
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod 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.cyanogenmod.setupwizard.cmstats;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import cyanogenmod.providers.CMSettings;
public class StatsUtils {
private static final String STATS_PACKAGE = "com.cyngn.stats";
public static boolean isStatsCollectionEnabled(Context context) {
return CMSettings.Secure.getInt(context.getContentResolver(),
CMSettings.Secure.STATS_COLLECTION, 1) != 0;
}
public static boolean isStatsPackageInstalled(Context context) {
try {
PackageInfo pi = context.getPackageManager().getPackageInfo(STATS_PACKAGE, 0);
return pi.applicationInfo.enabled
&& ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
}

View File

@@ -1,255 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.setup;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.Bundle;
import java.util.ArrayList;
public abstract class AbstractSetupData extends BroadcastReceiver implements SetupDataCallbacks {
private static final String TAG = AbstractSetupData.class.getSimpleName();
protected final Context mContext;
private ArrayList<SetupDataCallbacks> mListeners = new ArrayList<SetupDataCallbacks>();
private PageList mPageList;
private int mCurrentPageIndex = 0;
private boolean mIsResumed = false;
private boolean mIsFinished = false;
private OnResumeRunnable mOnResumeRunnable;
public AbstractSetupData(Context context) {
mContext = context;
mPageList = onNewPageList();
}
protected abstract PageList onNewPageList();
@Override
public void onPageLoaded(Page page) {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onPageLoaded(page);
}
}
@Override
public void onPageTreeChanged() {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onPageTreeChanged();
}
}
@Override
public void onFinish() {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onFinish();
}
}
@Override
public void finishSetup() {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).finishSetup();
}
}
@Override
public Page getPage(String key) {
return mPageList.getPage(key);
}
@Override
public Page getPage(int index) {
return mPageList.getPage(index);
}
public Page getCurrentPage() {
return mPageList.getPage(mCurrentPageIndex);
}
@Override
public boolean isCurrentPage(Page page) {
if (page == null) return false;
return page.getKey().equals(getCurrentPage().getKey());
}
public boolean isFirstPage() {
return mCurrentPageIndex == 0;
}
public boolean isLastPage() {
return mCurrentPageIndex == mPageList.size() - 1;
}
@Override
public void onNextPage() {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (getCurrentPage().doNextAction() == false) {
if (advanceToNextUnhidden()) {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onNextPage();
}
}
}
}
};
doPreviousNext(runnable);
}
@Override
public void onPreviousPage() {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (getCurrentPage().doPreviousAction() == false) {
if (advanceToPreviousUnhidden()) {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onPreviousPage();
}
}
}
}
};
doPreviousNext(runnable);
}
@Override
public void setCurrentPage(String key) {
if (mPageList.getPage(key) != null) {
mCurrentPageIndex = mPageList.getPageIndex(key);
}
}
public Page getNextPage(String key) {
if (mPageList.getPage(key) != null) {
int currentPageIndex = mPageList.getPageIndex(key);
return mPageList.getPage(currentPageIndex + 1);
}
return null;
}
private boolean advanceToNextUnhidden() {
while (mCurrentPageIndex < mPageList.size()) {
mCurrentPageIndex++;
if (!getCurrentPage().isHidden()) {
return true;
}
}
return false;
}
private boolean advanceToPreviousUnhidden() {
while (mCurrentPageIndex > 0) {
mCurrentPageIndex--;
if (!getCurrentPage().isHidden()) {
return true;
}
}
return false;
}
public void load(Bundle savedValues) {
for (String key : savedValues.keySet()) {
Page page = mPageList.getPage(key);
if (page != null) {
page.resetData(savedValues.getBundle(key));
}
}
}
private void doPreviousNext(Runnable runnable) {
if (mIsResumed) {
runnable.run();
} else {
mOnResumeRunnable = new OnResumeRunnable(runnable, this);
}
}
public void onDestroy() {
mOnResumeRunnable = null;
}
public void onPause() {
mIsResumed = false;
}
public void onResume() {
mIsResumed = true;
if (mOnResumeRunnable != null) {
mOnResumeRunnable.run();
}
}
public void finishPages() {
mIsFinished = true;
for (Page page : mPageList.values()) {
page.onFinishSetup();
}
}
@Override
public void addFinishRunnable(Runnable runnable) {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).addFinishRunnable(runnable);
}
}
public boolean isFinished() {
return mIsFinished;
}
public Bundle save() {
Bundle bundle = new Bundle();
for (Page page : mPageList.values()) {
bundle.putBundle(page.getKey(), page.getData());
}
return bundle;
}
public void registerListener(SetupDataCallbacks listener) {
mListeners.add(listener);
}
public void unregisterListener(SetupDataCallbacks listener) {
mListeners.remove(listener);
}
private static class OnResumeRunnable implements Runnable {
private final AbstractSetupData mAbstractSetupData;
private final Runnable mRunnable;
private OnResumeRunnable(Runnable runnable, AbstractSetupData abstractSetupData) {
mAbstractSetupData = abstractSetupData;
mRunnable = runnable;
}
@Override
public void run() {
mRunnable.run();
mAbstractSetupData.mOnResumeRunnable = null;
}
}
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.LoadingFragment;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class BluetoothSetupPage extends SetupPage {
public static final String TAG = "BluetoothSetupPage";
private static final String ACTION_CONNECT_INPUT =
"com.google.android.intent.action.CONNECT_INPUT";
private static final String INTENT_EXTRA_NO_INPUT_MODE = "no_input_mode";
private LoadingFragment mLoadingFragment;
public BluetoothSetupPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public SetupPageFragment getFragment(FragmentManager fragmentManager, int action) {
mLoadingFragment = (LoadingFragment)fragmentManager.findFragmentByTag(getKey());
if (mLoadingFragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
mLoadingFragment = new LoadingFragment();
mLoadingFragment.setArguments(args);
}
return mLoadingFragment;
}
@Override
public int getNextButtonTitleResId() {
return R.string.skip;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.loading;
}
@Override
public int getIconResId() {
return -1;
}
@Override
public void doLoadAction(FragmentManager fragmentManager, int action) {
super.doLoadAction(fragmentManager, action);
launchConnectInput();
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SetupWizardApp.REQUEST_CODE_SETUP_BLUETOOTH) {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.BLUETOOTH_SETUP, "success");
getCallbacks().onNextPage();
} else {
return false;
}
return true;
}
private void launchConnectInput() {
Intent intent = new Intent();
intent.setComponent(SetupWizardUtils.mTvAddAccessorySettingsActivity);
intent.setAction(ACTION_CONNECT_INPUT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(INTENT_EXTRA_NO_INPUT_MODE, true);
ActivityOptions options =
ActivityOptions.makeCustomAnimation(mContext,
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.BLUETOOTH_SETUP);
mLoadingFragment.startActivityForResult(intent,
SetupWizardApp.REQUEST_CODE_SETUP_BLUETOOTH, options.toBundle());
}
}

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.setup;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.telephony.TelephonyIntents;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import org.cyanogenmod.internal.util.PackageManagerUtils;
import java.util.ArrayList;
public class CMSetupWizardData extends AbstractSetupData {
private static final String TAG = CMSetupWizardData.class.getSimpleName();
private boolean mTimeSet = false;
private boolean mTimeZoneSet = false;
private boolean mMobileDataEnabled;
public CMSetupWizardData(Context context) {
super(context);
mMobileDataEnabled = SetupWizardUtils.isMobileDataEnabled(context);
}
@Override
protected PageList onNewPageList() {
ArrayList<Page> pages = new ArrayList<Page>();
if (SetupWizardUtils.hasLeanback(mContext)) {
pages.add(new BluetoothSetupPage(mContext, this));
}
pages.add(new WelcomePage(mContext, this));
pages.add(new DateTimePage(mContext, this));
if (SetupWizardUtils.hasWifi(mContext)) {
pages.add(new WifiSetupPage(mContext, this));
}
if (SetupWizardUtils.hasTelephony(mContext)) {
pages.add(new SimCardMissingPage(mContext, this)
.setHidden(isSimInserted()));
}
if (SetupWizardUtils.isMultiSimDevice(mContext)) {
pages.add(new ChooseDataSimPage(mContext, this)
.setHidden(!allSimsInserted()));
}
if (SetupWizardUtils.hasTelephony(mContext)) {
pages.add(new MobileDataPage(mContext, this)
.setHidden(!isSimInserted() || mMobileDataEnabled));
}
final boolean hasGMS = PackageManagerUtils
.isAppInstalled(mContext, "com.google.android.gms");
if (hasGMS) {
pages.add(new GmsAccountPage(mContext, this));
}
pages.add(new OtherSettingsPage(mContext, this).setHidden(!hasGMS));
if (SetupWizardUtils.hasFingerprint(mContext) && SetupWizardUtils.isOwner()) {
pages.add(new FingerprintSetupPage(mContext, this));
}
pages.add(new ScreenLockSetupPage(mContext, this));
pages.add(new FinishPage(mContext, this));
return new PageList(pages.toArray(new SetupPage[pages.size()]));
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
showHideDataSimPage();
showHideSimMissingPage();
showHideMobileDataPage();
} else if (intent.getAction()
.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
showHideMobileDataPage();
} else if (intent.getAction()
.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
showHideMobileDataPage();
} else if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED) ||
intent.getAction().equals(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE)) {
mTimeZoneSet = true;
showHideDateTimePage();
} else if (intent.getAction().equals(Intent.ACTION_TIME_CHANGED) ||
intent.getAction().equals(TelephonyIntents.ACTION_NETWORK_SET_TIME)) {
mTimeSet = true;
showHideDateTimePage();
}
}
private void showHideSimMissingPage() {
SimCardMissingPage simCardMissingPage =
(SimCardMissingPage) getPage(SimCardMissingPage.TAG);
if (simCardMissingPage != null) {
if (isSimInserted()) {
simCardMissingPage.setHidden(true);
if (isCurrentPage(simCardMissingPage)) {
onNextPage();
}
} else {
simCardMissingPage.setHidden(false);
}
}
}
private void showHideDataSimPage() {
ChooseDataSimPage chooseDataSimPage =
(ChooseDataSimPage) getPage(ChooseDataSimPage.TAG);
if (chooseDataSimPage != null) {
chooseDataSimPage.setHidden(!allSimsInserted());
}
}
private void showHideMobileDataPage() {
MobileDataPage mobileDataPage =
(MobileDataPage) getPage(MobileDataPage.TAG);
if (mobileDataPage != null) {
mobileDataPage.setHidden(!isSimInserted() || mMobileDataEnabled);
}
}
private void showHideDateTimePage() {
DateTimePage dateTimePage = (DateTimePage) getPage(DateTimePage.TAG);
if (dateTimePage != null) {
dateTimePage.setHidden(mTimeZoneSet & mTimeSet);
}
}
public IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
if (SetupWizardUtils.hasTelephony(mContext)) {
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
}
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIME);
filter.addAction(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
return filter;
}
// We only care that one sim is inserted
private boolean isSimInserted() {
TelephonyManager tm = TelephonyManager.from(mContext);
int simSlotCount = tm.getSimCount();
for (int i = 0; i < simSlotCount; i++) {
int state;
try {
state = tm.getSimState(i);
} catch (IllegalStateException ise) {
Log.e(TAG, "Unable to get sim state from TelephonyManager");
continue;
}
if (state != TelephonyManager.SIM_STATE_ABSENT
&& state != TelephonyManager.SIM_STATE_UNKNOWN
&& state != TelephonyManager.SIM_STATE_NOT_READY) {
return true;
}
}
return false;
}
// We only care that each slot has a sim
private boolean allSimsInserted() {
TelephonyManager tm = TelephonyManager.from(mContext);
int simSlotCount = tm.getSimCount();
for (int i = 0; i < simSlotCount; i++) {
int state = tm.getSimState(i);
if (state == TelephonyManager.SIM_STATE_ABSENT) {
return false;
}
}
return simSlotCount == SubscriptionManager.from(mContext).getActiveSubscriptionInfoCount();
}
}

View File

@@ -1,501 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.util.List;
public class ChooseDataSimPage extends SetupPage {
public static final String TAG = "ChooseDataSimPage";
public ChooseDataSimPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new ChooseDataSimFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_choose_data_sim;
}
@Override
public int getIconResId() {
return R.drawable.ic_sim;
}
public static class ChooseDataSimFragment extends SetupPageFragment {
private ViewGroup mPageView;
private ProgressBar mProgressBar;
private SparseArray<TextView> mNameViews;
private SparseArray<ImageView> mSignalViews;
private SparseArray<CheckBox> mCheckBoxes;
private SparseArray<View> mRows;
private Button mNextButton;
private TelephonyManager mPhone;
private SparseArray<SubscriptionInfo> mSubInfoRecords;
private SparseArray<SignalStrength> mSignalStrengths;
private SparseArray<ServiceState> mServiceStates;
private SparseArray<PhoneStateListener> mPhoneStateListeners;
private boolean mIsAttached = false;
private boolean mRadioReady = false;
private Context mContext;
private SubscriptionManager mSubscriptionManager;
private int mCurrentDataSubId;
// This is static because a user can click back mid operation.
// We want to persist what the user was changing to because of the
// async callback can sometimes take a long time.
private static int sChangingToDataSubId = -1;
private boolean mDisabledForSwitch = false;
private final Handler mHandler = new Handler();
private final Runnable mRadioReadyRunnable = new Runnable() {
@Override
public void run() {
// If we timeout out waiting for the radio, Oh well.
if (!mRadioReady) {
mRadioReady = true;
checkForRadioReady();
}
}
};
private View.OnClickListener mSetDataSimClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
SubscriptionInfo subInfoRecord = (SubscriptionInfo)view.getTag();
if (subInfoRecord != null) {
changeDataSub(subInfoRecord);
}
}
};
@Override
protected void initializePage() {
mPageView = (ViewGroup)mRootView.findViewById(R.id.page_view);
mProgressBar = (ProgressBar) mRootView.findViewById(R.id.progress);
mNextButton = (Button) getActivity().findViewById(R.id.next_button);
List<SubscriptionInfo> subInfoRecords = mSubscriptionManager.getActiveSubscriptionInfoList();
int simCount =
subInfoRecords != null ? subInfoRecords.size() : 0;
mSubInfoRecords = new SparseArray<SubscriptionInfo>(simCount);
for (SubscriptionInfo subInfoRecord : subInfoRecords) {
mSubInfoRecords.put(subInfoRecord.getSimSlotIndex(), subInfoRecord);
}
mNameViews = new SparseArray<TextView>(simCount);
mSignalViews = new SparseArray<ImageView>(simCount);
mCheckBoxes = new SparseArray<CheckBox>(simCount);
mRows = new SparseArray<View>(simCount);
mServiceStates = new SparseArray<ServiceState>(simCount);
mSignalStrengths = new SparseArray<SignalStrength>(simCount);
mPhoneStateListeners = new SparseArray<PhoneStateListener>(simCount);
LayoutInflater inflater = LayoutInflater.from(getActivity());
for (int i = 0; i < simCount; i++) {
View simRow = inflater.inflate(R.layout.data_sim_row, null);
mPageView.addView(simRow);
SubscriptionInfo subInfoRecord = mSubInfoRecords.valueAt(i);
simRow.setTag(subInfoRecord);
simRow.setOnClickListener(mSetDataSimClickListener);
int slot = subInfoRecord.getSimSlotIndex();
mNameViews.put(slot, (TextView) simRow.findViewById(R.id.sim_title));
mSignalViews.put(slot, (ImageView) simRow.findViewById(R.id.signal));
mCheckBoxes.put(slot, (CheckBox) simRow.findViewById(R.id.enable_check));
mRows.put(slot, simRow);
mPhoneStateListeners.put(slot, createPhoneStateListener(subInfoRecord));
mPageView.addView(inflater.inflate(R.layout.divider, null));
}
updateSignalStrengths();
updateCurrentDataSub();
}
@Override
protected int getLayoutResource() {
return R.layout.choose_data_sim_page;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity().getApplicationContext();
mSubscriptionManager = SubscriptionManager.from(mContext);
mCurrentDataSubId = mSubscriptionManager.getDefaultSubscriptionId();
if (sChangingToDataSubId == -1) {
sChangingToDataSubId = mCurrentDataSubId;
}
}
@Override
public void onResume() {
super.onResume();
mIsAttached = true;
mPhone = (TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE);
for (int i = 0; i < mPhoneStateListeners.size(); i++) {
mPhone.listen(mPhoneStateListeners.valueAt(i),
PhoneStateListener.LISTEN_SERVICE_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
);
}
mRadioReady = SetupWizardUtils.isRadioReady(mContext, null);
updateSignalStrengths();
updateCurrentDataSub();
checkForRadioReady();
if (mRadioReady) {
checkSimChangingState();
}
// Register for DDS changes
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
getActivity().registerReceiver(mIntentReceiver, filter, null, null);
}
@Override
public void onPause() {
super.onPause();
mIsAttached = false;
for (int i = 0; i < mPhoneStateListeners.size(); i++) {
mPhone.listen(mPhoneStateListeners.valueAt(i), PhoneStateListener.LISTEN_NONE);
}
getActivity().unregisterReceiver(mIntentReceiver);
}
private void ddsHasChanged(int subId) {
if (subId == sChangingToDataSubId) {
hideProgress();
enableViews(true);
}
}
private PhoneStateListener createPhoneStateListener(final SubscriptionInfo subInfoRecord) {
return new PhoneStateListener(subInfoRecord.getSubscriptionId()) {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
mSignalStrengths.put(subInfoRecord.getSimSlotIndex(), signalStrength);
updateSignalStrength(subInfoRecord);
}
@Override
public void onServiceStateChanged(ServiceState state) {
mRadioReady = SetupWizardUtils.isRadioReady(mContext, state);
checkForRadioReady();
mServiceStates.put(subInfoRecord.getSimSlotIndex(), state);
updateSignalStrength(subInfoRecord);
}
@Override
public void onDataConnectionStateChanged(int state) {
final int dataSubId = mSubscriptionManager.getDefaultSubscriptionId();
// In case the default sub changes from elsewhere. This shouldn't happen,
// but testcases can induce this.
if (dataSubId != mCurrentDataSubId &&
dataSubId != sChangingToDataSubId) {
sChangingToDataSubId = dataSubId;
updateCurrentDataSub();
}
if (mCurrentDataSubId != dataSubId) {
mCurrentDataSubId = dataSubId;
updateCurrentDataSub();
}
checkSimChangingState();
}
};
}
private void checkForRadioReady() {
if (mRadioReady) {
mHandler.removeCallbacks(mRadioReadyRunnable);
showPage();
checkSimChangingState();
return;
} else {
if (mTitleView != null) {
mTitleView.setText(R.string.loading);
}
enableViews(false);
showProgress();
if (!mHandler.hasCallbacks(mRadioReadyRunnable)) {
mHandler.postDelayed(mRadioReadyRunnable, SetupWizardApp.RADIO_READY_TIMEOUT);
}
}
}
private void showPage() {
final Context context = getActivity();
if (mTitleView != null) {
mTitleView.setText(mPage.getTitleResId());
}
mPageView.setVisibility(View.VISIBLE);
if (context != null && getUserVisibleHint() && !mPageView.isShown()) {
mPageView.startAnimation(
AnimationUtils.loadAnimation(context, R.anim.translucent_enter));
}
}
private void showProgress() {
final Context context = getActivity();
if (context != null && getUserVisibleHint() && !mProgressBar.isShown()) {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(context, R.anim.translucent_enter));
}
}
private void hideProgress() {
final Context context = getActivity();
if (context != null && getUserVisibleHint() && mProgressBar.isShown()) {
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(context, R.anim.translucent_exit));
mProgressBar.setVisibility(View.INVISIBLE);
}
}
private void updateSignalStrengths() {
if (mIsAttached) {
for (int i = 0; i < mSubInfoRecords.size(); i++) {
updateSignalStrength(mSubInfoRecords.valueAt(i));
}
}
}
private void changeDataSub(SubscriptionInfo subInfoRecord) {
if (sChangingToDataSubId != subInfoRecord.getSubscriptionId()) {
sChangingToDataSubId = subInfoRecord.getSubscriptionId();
mSubscriptionManager.setDefaultDataSubId(sChangingToDataSubId);
setDataSubChecked(subInfoRecord);
}
checkSimChangingState();
}
private void checkSimChangingState() {
if (mIsAttached && mRadioReady) {
if (mCurrentDataSubId != sChangingToDataSubId) {
showProgress();
enableViews(false);
} else {
hideProgress();
enableViews(true);
}
}
}
private void setDataSubChecked(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
for (int i = 0; i < mCheckBoxes.size(); i++) {
if (subInfoRecord.getSimSlotIndex() == i) {
mCheckBoxes.get(i).setChecked(true);
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.PREFERRED_DATA_SIM,
SetupStats.Label.SLOT, String.valueOf(i + 1));
} else {
mCheckBoxes.get(i).setChecked(false);
}
}
}
}
private void updateCurrentDataSub() {
if (mIsAttached) {
for (int i = 0; i < mSubInfoRecords.size(); i++) {
SubscriptionInfo subInfoRecord = mSubInfoRecords.valueAt(i);
mCheckBoxes.get(i).setChecked(mSubscriptionManager.getDefaultSubscriptionId()
== subInfoRecord.getSubscriptionId());
}
}
}
private void enableViews(boolean enabled) {
mDisabledForSwitch = !enabled;
enableRows(enabled);
mNextButton.setEnabled(enabled);
}
private void enableRows(boolean enabled) {
for (int i = 0; i < mRows.size(); i++) {
final View v = mRows.get(i);
v.setEnabled(enabled);
final SubscriptionInfo subInfoRecord = (SubscriptionInfo)v.getTag();
if (subInfoRecord != null) {
updateCarrierText(subInfoRecord);
}
}
}
private void updateCarrierText(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
String name = mPhone.getSimOperatorName(subInfoRecord.getSubscriptionId());
if (TextUtils.isEmpty(name)) {
name = mPhone.getNetworkOperatorName(subInfoRecord.getSubscriptionId());
}
ServiceState serviceState = mServiceStates.get(subInfoRecord.getSimSlotIndex());
final int slot = subInfoRecord.getSimSlotIndex();
final View v = mRows.get(slot);
if (TextUtils.isEmpty(name)) {
if (serviceState != null && serviceState.isEmergencyOnly()) {
name = getString(R.string.setup_mobile_data_emergency_only);
} else {
name = getString(R.string.setup_mobile_data_no_service);
}
if (v != null) {
v.setEnabled(false);
}
} else {
if (v != null && !mDisabledForSwitch) {
v.setEnabled(true);
}
}
String formattedName =
getString(R.string.data_sim_name,
slot + 1, name);
mNameViews.get(slot).setText(formattedName);
}
}
private void updateSignalStrength(SubscriptionInfo subInfoRecord) {
if (mIsAttached) {
ImageView signalView = mSignalViews.get(subInfoRecord.getSimSlotIndex());
SignalStrength signalStrength = mSignalStrengths.get(subInfoRecord.getSimSlotIndex());
if (!hasService(subInfoRecord)) {
signalView.setImageResource(R.drawable.ic_signal_no_signal);
} else {
if (signalStrength != null) {
int resId;
switch (signalStrength.getLevel()) {
case 4:
resId = R.drawable.ic_signal_4;
break;
case 3:
resId = R.drawable.ic_signal_3;
break;
case 2:
resId = R.drawable.ic_signal_2;
break;
case 1:
resId = R.drawable.ic_signal_1;
break;
default:
resId = R.drawable.ic_signal_0;
break;
}
signalView.setImageResource(resId);
}
}
updateCarrierText(subInfoRecord);
}
}
private boolean hasService(SubscriptionInfo subInfoRecord) {
boolean retVal;
ServiceState serviceState = mServiceStates.get(subInfoRecord.getSimSlotIndex());
if (serviceState != null) {
// Consider the device to be in service if either voice or data service is available.
// Some SIM cards are marketed as data-only and do not support voice service, and on
// these SIM cards, we want to show signal bars for data service as well as the "no
// service" or "emergency calls only" text that indicates that voice is not available.
switch(serviceState.getVoiceRegState()) {
case ServiceState.STATE_POWER_OFF:
retVal = false;
break;
case ServiceState.STATE_OUT_OF_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
retVal = serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
break;
default:
retVal = true;
}
} else {
retVal = false;
}
return retVal;
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final Activity activity = getActivity();
if (activity != null) {
ddsHasChanged(intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1));
}
}
};
}
}

View File

@@ -1,129 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
public class FingerprintSetupPage extends SetupPage {
private static final String TAG = "FingerprintSetupPage";
public FingerprintSetupPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new FingerprintSetupFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public int getNextButtonTitleResId() {
return R.string.skip;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.fingerprint_setup_title;
}
@Override
public int getIconResId() {
return R.drawable.ic_fingerprint;
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (SetupWizardApp.REQUEST_CODE_SETUP_FINGERPRINT == requestCode) {
if (resultCode == Activity.RESULT_OK) {
getCallbacks().onNextPage();
}
}
return true;
}
public static class FingerprintSetupFragment extends SetupPageFragment {
private TextView mSetupFingerprint;
@Override
protected void initializePage() {
mSetupFingerprint = (TextView) mRootView.findViewById(R.id.setup_fingerprint);
mSetupFingerprint.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchFingerprintSetup();
}
});
}
@Override
protected int getLayoutResource() {
return R.layout.setup_fingerprint;
}
private void launchFingerprintSetup() {
Intent intent = new Intent(SetupWizardApp.ACTION_SETUP_FINGERPRINT);
intent.putExtra(SetupWizardApp.EXTRA_FIRST_RUN, true);
intent.putExtra(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
intent.putExtra(SetupWizardApp.EXTRA_USE_IMMERSIVE, true);
intent.putExtra(SetupWizardApp.EXTRA_THEME, SetupWizardApp.EXTRA_MATERIAL_LIGHT);
intent.putExtra(SetupWizardApp.EXTRA_AUTO_FINISH, false);
/*intent.putExtra(LockPatternUtils.LOCKSCREEN_FINGERPRINT_FALLBACK, true);*/
intent.putExtra(SetupWizardApp.EXTRA_TITLE,
getString(R.string.settings_fingerprint_setup_title));
intent.putExtra(SetupWizardApp.EXTRA_DETAILS,
getString(R.string.settings_fingerprint_setup_details));
ActivityOptions options =
ActivityOptions.makeCustomAnimation(getActivity(),
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.FINGERPRINT_SETUP);
startActivityForResult(intent, SetupWizardApp.REQUEST_CODE_SETUP_FINGERPRINT,
options.toBundle());
}
}
}

View File

@@ -1,123 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.ui.SetupWizardActivity;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.lang.ref.WeakReference;
public class FinishPage extends SetupPage {
public static final String TAG = "FinishPage";
private static final String KEY_MESSENGER = "key_messenger";
private FinishFragment mFinishFragment;
public FinishPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
mFinishFragment = (FinishFragment)fragmentManager.findFragmentByTag(getKey());
if (mFinishFragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
args.putParcelable(KEY_MESSENGER, new Messenger(mHandler));
mFinishFragment = new FinishFragment();
mFinishFragment.setArguments(args);
}
return mFinishFragment;
}
private final PageHandler mHandler = new PageHandler(this);
private static class PageHandler extends Handler {
private final WeakReference<FinishPage> mPage;
private PageHandler(final FinishPage page) {
mPage = new WeakReference<>(page);
}
@Override
public void handleMessage(final Message msg) {
}
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_complete;
}
@Override
public int getIconResId() {
return -1;
}
@Override
public boolean doNextAction() {
getCallbacks().onFinish();
return true;
}
@Override
public int getNextButtonTitleResId() {
return R.string.start;
}
public static class FinishFragment extends SetupPageFragment {
@Override
protected void initializePage() {
final Activity activity = getActivity();
if (activity == null) {
return;
}
}
@Override
protected int getLayoutResource() {
return R.layout.setup_finished_page;
}
}
}

View File

@@ -1,325 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
public class MobileDataPage extends SetupPage {
public static final String TAG = "MobileDataPage";
private static final int DC_READY_TIMEOUT = 20 * 1000;
public MobileDataPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new MobileDataFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_mobile_data;
}
@Override
public int getIconResId() {
return R.drawable.ic_mobile_data;
}
public static class MobileDataFragment extends SetupPageFragment {
private ViewGroup mPageView;
private ProgressBar mProgressBar;
private View mEnableDataRow;
private Switch mEnableMobileData;
private ImageView mSignalView;
private TextView mNameView;
private Button mNextButton;
private TelephonyManager mPhone;
private SignalStrength mSignalStrength;
private ServiceState mServiceState;
private boolean mIsAttached = false;
private Context mContext;
private final Handler mHandler = new Handler();
private final Runnable mRadioReadyRunnable = new Runnable() {
@Override
public void run() {
hideWaitForRadio();
}
};
private final Runnable mDataConnectionReadyRunnable = new Runnable() {
@Override
public void run() {
onDataStateReady();
}
};
private PhoneStateListener mPhoneStateListener =
new PhoneStateListener(SubscriptionManager.getDefaultSubscriptionId()) {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
mSignalStrength = signalStrength;
updateSignalStrength();
}
@Override
public void onServiceStateChanged(ServiceState state) {
if (SetupWizardUtils.isRadioReady(mContext, state)) {
hideWaitForRadio();
}
mServiceState = state;
updateSignalStrength();
}
@Override
public void onDataConnectionStateChanged(int state) {
if (state == TelephonyManager.DATA_CONNECTED) {
onDataStateReady();
}
}
};
private View.OnClickListener mEnableDataClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean checked = !mEnableMobileData.isChecked();
SetupWizardUtils.setMobileDataEnabled(getActivity(), checked);
mEnableMobileData.setChecked(checked);
if (checked && !SetupWizardUtils.isWifiConnected(mContext)) {
waitForData();
} else {
onDataStateReady();
}
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.ENABLE_MOBILE_DATA,
SetupStats.Label.CHECKED, String.valueOf(checked));
}
};
@Override
protected void initializePage() {
mPageView = (ViewGroup)mRootView.findViewById(R.id.page_view);
mProgressBar = (ProgressBar) mRootView.findViewById(R.id.progress);
mEnableDataRow = mRootView.findViewById(R.id.data);
mEnableDataRow.setOnClickListener(mEnableDataClickListener);
mEnableMobileData = (Switch) mRootView.findViewById(R.id.data_switch);
mSignalView = (ImageView) mRootView.findViewById(R.id.signal);
mNameView = (TextView) mRootView.findViewById(R.id.enable_data_title);
mNextButton = (Button) getActivity().findViewById(R.id.next_button);
updateDataConnectionStatus();
updateSignalStrength();
}
@Override
protected int getLayoutResource() {
return R.layout.mobile_data_settings;
}
@Override
public void onResume() {
super.onResume();
mIsAttached = true;
mContext = getActivity().getApplicationContext();
mPhone = (TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE);
mPhone.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
updateDataConnectionStatus();
updateSignalStrength();
if (SetupWizardUtils.isRadioReady(mContext, null)) {
hideWaitForRadio();
} else if (mTitleView != null) {
mTitleView.setText(R.string.loading);
mHandler.postDelayed(mRadioReadyRunnable, SetupWizardApp.RADIO_READY_TIMEOUT);
}
}
@Override
public void onPause() {
super.onPause();
mIsAttached = false;
mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
}
private void hideWaitForRadio() {
if (getUserVisibleHint() && mProgressBar.isShown()) {
mHandler.removeCallbacks(mRadioReadyRunnable);
if (mTitleView != null) {
mTitleView.setText(mPage.getTitleResId());
}
// Something else, like data enablement, may have grabbed
// the "hold" status. Kill it only if "Next" is active
if (mNextButton.isEnabled()) {
mProgressBar.setVisibility(View.INVISIBLE);
mPageView.setVisibility(View.VISIBLE);
mPageView.startAnimation(
AnimationUtils.loadAnimation(getActivity(), R.anim.translucent_enter));
}
}
}
private void waitForData() {
if (getUserVisibleHint() && !mProgressBar.isShown()) {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(getActivity(), R.anim.translucent_enter));
mEnableDataRow.setEnabled(false);
mNextButton.setEnabled(false);
mHandler.postDelayed(mDataConnectionReadyRunnable, DC_READY_TIMEOUT);
}
}
private void onDataStateReady() {
mHandler.removeCallbacks(mDataConnectionReadyRunnable);
if ((getUserVisibleHint() && mProgressBar.isShown()) ||
!mNextButton.isEnabled()) {
mProgressBar.startAnimation(
AnimationUtils.loadAnimation(getActivity(), R.anim.translucent_exit));
mProgressBar.setVisibility(View.INVISIBLE);
mEnableDataRow.setEnabled(true);
mNextButton.setEnabled(true);
}
}
private void updateCarrierText() {
if (mIsAttached) {
String name = mPhone.getSimOperatorName(SubscriptionManager.getDefaultSubscriptionId());
if (TextUtils.isEmpty(name)) {
name = mPhone.getNetworkOperatorName(SubscriptionManager.getDefaultSubscriptionId());
}
if (TextUtils.isEmpty(name)) {
if (mServiceState != null && mServiceState.isEmergencyOnly()) {
name = getString(R.string.setup_mobile_data_emergency_only);
} else {
name = getString(R.string.setup_mobile_data_no_service);
}
}
mNameView.setText(name);
}
}
private void updateSignalStrength() {
if (mIsAttached) {
if (!hasService()) {
mSignalView.setImageResource(R.drawable.ic_signal_no_signal);
} else {
if (mSignalStrength != null) {
int resId;
switch (mSignalStrength.getLevel()) {
case 4:
resId = R.drawable.ic_signal_4;
break;
case 3:
resId = R.drawable.ic_signal_3;
break;
case 2:
resId = R.drawable.ic_signal_2;
break;
case 1:
resId = R.drawable.ic_signal_1;
break;
default:
resId = R.drawable.ic_signal_0;
break;
}
mSignalView.setImageResource(resId);
}
}
updateCarrierText();
}
}
private void updateDataConnectionStatus() {
mEnableMobileData.setChecked(SetupWizardUtils.isMobileDataEnabled(getActivity()));
}
private boolean hasService() {
boolean retVal;
if (mServiceState != null) {
// Consider the device to be in service if either voice or data service is available.
// Some SIM cards are marketed as data-only and do not support voice service, and on
// these SIM cards, we want to show signal bars for data service as well as the "no
// service" or "emergency calls only" text that indicates that voice is not available.
switch(mServiceState.getVoiceRegState()) {
case ServiceState.STATE_POWER_OFF:
retVal = false;
break;
case ServiceState.STATE_OUT_OF_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
break;
default:
retVal = true;
}
} else {
retVal = false;
}
return retVal;
}
}
}

View File

@@ -1,269 +0,0 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
public class OtherSettingsPage extends SetupPage {
public static final String TAG = "OtherSettingsPage";
public OtherSettingsPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new OtherSettingsFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_location;
}
@Override
public int getIconResId() {
return R.drawable.ic_location;
}
public static class OtherSettingsFragment extends SetupPageFragment {
private View mLocationRow;
private View mBatteryRow;
private View mNetworkRow;
private CheckBox mNetwork;
private CheckBox mBattery;
private CheckBox mLocationAccess;
private ContentResolver mContentResolver;
/** Broadcast intent action when the location mode is about to change. */
private static final String MODE_CHANGING_ACTION =
"com.android.settings.location.MODE_CHANGING";
private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
private static final String NEW_MODE_KEY = "NEW_MODE";
private int mCurrentMode = Settings.Secure.LOCATION_MODE_OFF;
private BroadcastReceiver mReceiver;
private View.OnClickListener mLocationClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleLocationAccess(!mLocationAccess.isChecked());
}
};
private View.OnClickListener mBatteryClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleBatterySaving(!mBattery.isChecked());
}
};
private View.OnClickListener mNetworkClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
onToggleNetwork(!mNetwork.isChecked());
}
};
@Override
protected void initializePage() {
final boolean hasTelephony = SetupWizardUtils.hasTelephony(getActivity());
mContentResolver = getActivity().getContentResolver();
TextView summaryView = (TextView) mRootView.findViewById(android.R.id.summary);
summaryView.setText(R.string.location_services_summary);
mLocationRow = mRootView.findViewById(R.id.location);
mLocationRow.setOnClickListener(mLocationClickListener);
mLocationAccess = (CheckBox) mRootView.findViewById(R.id.location_checkbox);
mBatteryRow = mRootView.findViewById(R.id.battery_saving);
mBatteryRow.setOnClickListener(mBatteryClickListener);
mBattery = (CheckBox) mRootView.findViewById(R.id.battery_saving_checkbox);
mNetworkRow = mRootView.findViewById(R.id.network);
mNetworkRow.setOnClickListener(mNetworkClickListener);
mNetwork = (CheckBox) mRootView.findViewById(R.id.network_checkbox);
TextView networkSummary = (TextView) mRootView.findViewById(R.id.network_summary);
if (hasTelephony) {
networkSummary.setText(R.string.location_network_telephony);
} else {
networkSummary.setText(R.string.location_network);
}
}
@Override
protected int getLayoutResource() {
return R.layout.location_settings;
}
@Override
public void onResume() {
super.onResume();
refreshLocationMode();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Received location mode change intent: " + intent);
}
refreshLocationMode();
}
};
}
private void setLocationMode(int mode) {
Intent intent = new Intent(MODE_CHANGING_ACTION);
intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
intent.putExtra(NEW_MODE_KEY, mode);
getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
Settings.Secure.putInt(mContentResolver, Settings.Secure.LOCATION_MODE, mode);
refreshLocationMode();
}
private void refreshLocationMode() {
int mode = Settings.Secure.getInt(mContentResolver, Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
if (mCurrentMode != mode) {
mCurrentMode = mode;
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Location mode has been changed");
}
updateLocationToggles(mode);
}
}
private void updateLocationToggles(int mode) {
switch (mode) {
case Settings.Secure.LOCATION_MODE_OFF:
mLocationAccess.setChecked(false);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
mLocationAccess.setChecked(true);
mBattery.setChecked(false);
mBattery.setEnabled(true);
mBatteryRow.setEnabled(true);
mNetwork.setChecked(false);
mNetwork.setEnabled(true);
mNetworkRow.setEnabled(true);
break;
case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
mLocationAccess.setChecked(true);
mBattery.setChecked(true);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
mLocationAccess.setChecked(true);
mNetwork.setChecked(true);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
break;
default:
mLocationAccess.setChecked(false);
mBattery.setChecked(false);
mBattery.setEnabled(false);
mBatteryRow.setEnabled(false);
mNetwork.setChecked(false);
mNetwork.setEnabled(false);
mNetworkRow.setEnabled(false);
break;
}
}
private void onToggleLocationAccess(boolean checked) {
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.ENABLE_LOCATION,
SetupStats.Label.CHECKED, String.valueOf(checked));
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_OFF);
}
}
private void onToggleBatterySaving(boolean checked) {
/* SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.ENABLE_BATTERY_SAVING_LOCATION,
SetupStats.Label.CHECKED, String.valueOf(checked)); */
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
}
}
private void onToggleNetwork(boolean checked) {
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
SetupStats.Action.ENABLE_NETWORK_LOCATION,
SetupStats.Label.CHECKED, String.valueOf(checked));
if (checked) {
setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
} else {
setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
}
}
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.os.Bundle;
public interface Page {
public static final String KEY_PAGE_ARGUMENT = "key_arg";
public static final String KEY_PAGE_ACTION= "action";
public static final int ACTION_NEXT = 1;
public static final int ACTION_PREVIOUS = 2;
public String getKey();
public int getTitleResId();
public int getIconResId();
public int getButtonBarBackgroundColorId();
public int getPrevButtonTitleResId();
public int getNextButtonTitleResId();
public Fragment getFragment(FragmentManager fragmentManager, int action);
public Bundle getData();
public void resetData(Bundle data);
public boolean isRequired();
public Page setRequired(boolean required);
public boolean isHidden();
public Page setHidden(boolean hidden);
public boolean doPreviousAction();
public boolean doNextAction();
public void doLoadAction(FragmentManager fragmentManager, int action);
public void onFinishSetup();
public boolean onActivityResult(int requestCode, int resultCode, Intent data);
public SetupDataCallbacks getCallbacks();
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.setup;
import android.text.TextUtils;
import java.util.LinkedHashMap;
public class PageList extends LinkedHashMap<String, Page> {
public PageList(Page... pages) {
for (Page page : pages) {
put(page.getKey(), page);
}
}
public Page getPage(String key) {
return get(key);
}
public int getPageIndex(String key) {
int i=0;
for (Page page : values()) {
if (TextUtils.equals(page.getKey(), key)) {
return i;
}
i++;
}
return i;
}
public Page getPage(int index) {
int i=0;
for (Page page : values()) {
if (i == index) {
return page;
}
i++;
}
return null;
}
}

View File

@@ -1,122 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
public class ScreenLockSetupPage extends SetupPage {
private static final String TAG = "ScreenLockSetupPage";
public ScreenLockSetupPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new LockscreenSetupFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public int getNextButtonTitleResId() {
return R.string.skip;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.lockscreen_setup_title;
}
@Override
public int getIconResId() {
return R.drawable.ic_lock_screen;
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (SetupWizardApp.REQUEST_CODE_SETUP_LOCKSCREEN == requestCode) {
if (resultCode == Activity.RESULT_OK || resultCode == Activity.RESULT_FIRST_USER) {
getCallbacks().onNextPage();
}
}
return true;
}
public static class LockscreenSetupFragment extends SetupPageFragment {
private Button mSetupLockscreen;
@Override
protected void initializePage() {
mSetupLockscreen = (Button) mRootView.findViewById(R.id.setup_lockscreen);
mSetupLockscreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchLockscreenSetup();
}
});
}
@Override
protected int getLayoutResource() {
return R.layout.setup_lockscreen;
}
private void launchLockscreenSetup() {
Intent intent = new Intent(SetupWizardApp.ACTION_SETUP_LOCKSCREEN);
intent.putExtra(SetupWizardApp.EXTRA_TITLE,
getString(R.string.settings_lockscreen_setup_title));
intent.putExtra(SetupWizardApp.EXTRA_DETAILS,
getString(R.string.settings_lockscreen_setup_details));
ActivityOptions options =
ActivityOptions.makeCustomAnimation(getActivity(),
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.LOCKSCREEN_SETUP);
startActivityForResult(intent, SetupWizardApp.REQUEST_CODE_SETUP_LOCKSCREEN,
options.toBundle());
}
}
}

View File

@@ -1,31 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.setup;
public interface SetupDataCallbacks {
void onNextPage();
void onPreviousPage();
void onPageLoaded(Page page);
void onPageTreeChanged();
void onFinish();
void finishSetup();
boolean isCurrentPage(Page page);
Page getPage(String key);
Page getPage(int key);
void setCurrentPage(String key);
void addFinishRunnable(Runnable runnable);
}

View File

@@ -1,145 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.setup;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.transition.Slide;
import android.transition.Transition;
import android.view.Gravity;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
public abstract class SetupPage implements Page {
private final SetupDataCallbacks mCallbacks;
private Bundle mData = new Bundle();
private boolean mRequired = false;
private boolean mHidden = false;
protected final Context mContext;
protected SetupPage(Context context, SetupDataCallbacks callbacks) {
mContext = context;
mCallbacks = callbacks;
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
return null;
}
@Override
public int getButtonBarBackgroundColorId() {
return R.color.button_bar_background;
}
@Override
public int getPrevButtonTitleResId() {
return -1;
}
@Override
public int getNextButtonTitleResId() {
return R.string.next;
}
@Override
public boolean doNextAction() {
return false;
}
@Override
public boolean doPreviousAction() {
return false;
}
@Override
public void onFinishSetup() {}
@Override
public void doLoadAction(FragmentManager fragmentManager, int action) {
Fragment fragment = getFragment(fragmentManager, action);
if (action == Page.ACTION_NEXT) {
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK,
SetupStats.Action.NEXT_BUTTON, getKey(),
String.valueOf(System.currentTimeMillis()));
Transition t = new Slide(Gravity.RIGHT);
fragment.setEnterTransition(t);
fragmentManager.beginTransaction()
.replace(R.id.content,fragment, getKey())
.commit();
} else {
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK,
SetupStats.Action.PREVIOUS_BUTTON, getKey(),
String.valueOf(System.currentTimeMillis()));
Transition t = new Slide(Gravity.LEFT);
fragment.setEnterTransition(t);
fragmentManager.beginTransaction()
.replace(R.id.content, fragment, getKey())
.commit();
}
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
return false;
}
@Override
public boolean isRequired() {
return mRequired;
}
@Override
public Page setRequired(boolean required) {
mRequired = required;
return this;
}
@Override
public boolean isHidden() {
return mHidden;
}
@Override
public Page setHidden(boolean hidden) {
mHidden = hidden;
return this;
}
@Override
public Bundle getData() {
return mData;
}
@Override
public void resetData(Bundle data) {
mData = data;
mCallbacks.onPageLoaded(this);
}
public SetupDataCallbacks getCallbacks() {
return mCallbacks;
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright (C) 2014 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.os.Bundle;
import android.widget.ImageView;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.ui.SetupWizardActivity;
public class SimCardMissingPage extends SetupPage {
public static final String TAG = "SimCardMissingPage";
private static final int SIM_DEFAULT = 0;
private static final int SIM_SIDE = 1;
private static final int SIM_BACK = 2;
public SimCardMissingPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
Fragment fragment = fragmentManager.findFragmentByTag(getKey());
if (fragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
fragment = new SimCardMissingFragment();
fragment.setArguments(args);
}
return fragment;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_sim_missing;
}
@Override
public int getIconResId() {
return R.drawable.ic_sim;
}
@Override
public int getNextButtonTitleResId() {
return R.string.skip;
}
public static class SimCardMissingFragment extends SetupPageFragment {
@Override
protected void initializePage() {
final int simLocation = getResources().getInteger(
R.integer.sim_image_type);
ImageView simLogo = ((ImageView)mRootView.findViewById(R.id.sim_slot_image));
switch (simLocation) {
case SIM_SIDE:
simLogo.setImageResource(R.drawable.sim_side);
break;
case SIM_BACK:
simLogo.setImageResource(R.drawable.sim_back);
break;
default:
simLogo.setImageResource(R.drawable.sim);
simLogo.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
}
}
@Override
protected int getLayoutResource() {
return R.layout.sim_missing_page;
}
}
}

View File

@@ -1,129 +0,0 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
public class WelcomePage extends SetupPage {
public static final String TAG = "WelcomePage";
private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
private WelcomeFragment mWelcomeFragment;
public WelcomePage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment(FragmentManager fragmentManager, int action) {
mWelcomeFragment = (WelcomeFragment)fragmentManager.findFragmentByTag(getKey());
if (mWelcomeFragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
mWelcomeFragment = new WelcomeFragment();
mWelcomeFragment.setArguments(args);
}
return mWelcomeFragment;
}
@Override
public int getTitleResId() {
return R.string.os_name;
}
@Override
public int getIconResId() {
return -1;
}
@Override
public boolean doNextAction() {
return super.doNextAction();
}
@Override
public boolean doPreviousAction() {
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
ActivityOptions options =
ActivityOptions.makeCustomAnimation(mContext,
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.BUTTON_CLICK, SetupStats.Label.EMERGENCY_CALL);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.EMERGENCY_CALL);
mContext.startActivity(intent, options.toBundle());
return true;
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SetupWizardApp.REQUEST_CODE_UNLOCK) {
if (resultCode == Activity.RESULT_OK) {
((SetupWizardApp) mContext.getApplicationContext()).setIsAuthorized(true);
getCallbacks().onNextPage();
return true;
}
}
return false;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getNextButtonTitleResId() {
return R.string.next;
}
@Override
public int getPrevButtonTitleResId() {
return R.string.emergency_call;
}
public static class WelcomeFragment extends SetupPageFragment {
@Override
protected void initializePage() {
}
@Override
protected int getLayoutResource() {
return R.layout.setup_welcome_page;
}
}
}

View File

@@ -1,270 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.setup;
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.net.CaptivePortal;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.ui.LoadingFragment;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
public class WifiSetupPage extends SetupPage {
public static final String TAG = "WifiSetupPage";
private static final String DEFAULT_SERVER = "clients3.google.com";
private static final int CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS = 10000;
private LoadingFragment mLoadingFragment;
private URL mCaptivePortalUrl;
private boolean mIsCaptivePortal = false;
private final Handler mHandler = new Handler();
private String mResponseToken;
private Runnable mFinishCaptivePortalCheckRunnable = new Runnable() {
@Override
public void run() {
if (mIsCaptivePortal) {
try {
mResponseToken = String.valueOf(new Random().nextLong());
final Intent intent = new Intent(
ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
intent.putExtra(Intent.EXTRA_TEXT, mResponseToken);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK,
ConnectivityManager.from(mContext)
.getNetworkForType(ConnectivityManager.TYPE_WIFI));
intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
new CaptivePortal(new ICaptivePortal.Stub() {
@Override
public void appResponse(int response) {}
}));
intent.putExtra("status_bar_color",
mContext.getResources().getColor(R.color.primary_dark));
intent.putExtra("action_bar_color", mContext.getResources().getColor(
R.color.primary_dark));
intent.putExtra("progress_bar_color", mContext.getResources().getColor(
R.color.accent));
ActivityOptions options =
ActivityOptions.makeCustomAnimation(mContext,
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.CAPTIVE_PORTAL_LOGIN);
mLoadingFragment.startActivityForResult(intent,
SetupWizardApp.REQUEST_CODE_SETUP_CAPTIVE_PORTAL,
options.toBundle());
} catch (Exception e) {
//Oh well
Log.e(TAG, "No captive portal activity found" + e);
if (getCallbacks().isCurrentPage(WifiSetupPage.this)) {
getCallbacks().onNextPage();
}
}
} else {
if (getCallbacks().isCurrentPage(WifiSetupPage.this)) {
getCallbacks().onNextPage();
}
}
}
};
public WifiSetupPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
String server = Settings.Global.getString(context.getContentResolver(), "captive_portal_server");
if (server == null) server = DEFAULT_SERVER;
try {
mCaptivePortalUrl = new URL("http://" + server + "/generate_204");
} catch (MalformedURLException e) {
Log.e(TAG, "Not a valid url" + e);
}
}
@Override
public SetupPageFragment getFragment(FragmentManager fragmentManager, int action) {
mLoadingFragment = (LoadingFragment)fragmentManager.findFragmentByTag(getKey());
if (mLoadingFragment == null) {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
args.putInt(Page.KEY_PAGE_ACTION, action);
mLoadingFragment = new LoadingFragment();
mLoadingFragment.setArguments(args);
}
return mLoadingFragment;
}
@Override
public int getNextButtonTitleResId() {
return R.string.skip;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.loading;
}
@Override
public int getIconResId() {
return -1;
}
@Override
public void doLoadAction(FragmentManager fragmentManager, int action) {
super.doLoadAction(fragmentManager, action);
launchWifiSetup();
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SetupWizardApp.REQUEST_CODE_SETUP_WIFI) {
if (resultCode == Activity.RESULT_CANCELED) {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.WIFI_SETUP, "canceled");
getCallbacks().onPreviousPage();
} else if (resultCode == Activity.RESULT_OK) {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.WIFI_SETUP, "success");
checkForCaptivePortal();
} else {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.WIFI_SETUP, "skipped");
getCallbacks().onNextPage();
}
} else if (requestCode == SetupWizardApp.REQUEST_CODE_SETUP_CAPTIVE_PORTAL) {
if (data == null) {
launchWifiSetup();
return true;
}
String token = data.getStringExtra("response_token");
if (token != null && !token.equals(mResponseToken)) {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.CAPTIVE_PORTAL_LOGIN, "token_mismatch");
launchWifiSetup();
} else {
if (resultCode == Activity.RESULT_CANCELED) {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.CAPTIVE_PORTAL_LOGIN, "canceled");
launchWifiSetup();
} else {
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_RESULT,
SetupStats.Label.CAPTIVE_PORTAL_LOGIN, "success");
getCallbacks().onNextPage();
}
}
} else {
return false;
}
return true;
}
private void checkForCaptivePortal() {
new Thread() {
@Override
public void run() {
mIsCaptivePortal = isCaptivePortal();
mHandler.post(mFinishCaptivePortalCheckRunnable);
}
}.start();
}
// Don't run on UI thread
private boolean isCaptivePortal() {
if (mCaptivePortalUrl == null) return false;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) mCaptivePortalUrl.openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS);
urlConnection.setReadTimeout(CAPTIVE_PORTAL_SOCKET_TIMEOUT_MS);
urlConnection.setUseCaches(false);
urlConnection.getInputStream();
// We got a valid response, but not from the real google
final int responseCode = urlConnection.getResponseCode();
if (responseCode == 408 || responseCode == 504) {
// If we timeout here, we'll try and go through captive portal login
return true;
}
return urlConnection.getResponseCode() != 204;
} catch (IOException e) {
Log.e(TAG, "Captive portal check - probably not a portal: exception "
+ e);
return false;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
private void launchWifiSetup() {
SetupWizardUtils.tryEnablingWifi(mContext);
Intent intent = new Intent(SetupWizardApp.ACTION_SETUP_WIFI);
if (SetupWizardUtils.hasLeanback(mContext)) {
intent.setComponent(SetupWizardUtils.mTvwifisettingsActivity);
}
intent.putExtra(SetupWizardApp.EXTRA_FIRST_RUN, true);
intent.putExtra(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
intent.putExtra(SetupWizardApp.EXTRA_USE_IMMERSIVE, true);
intent.putExtra(SetupWizardApp.EXTRA_THEME, SetupWizardApp.EXTRA_MATERIAL_LIGHT);
intent.putExtra(SetupWizardApp.EXTRA_AUTO_FINISH, false);
ActivityOptions options =
ActivityOptions.makeCustomAnimation(mContext,
android.R.anim.fade_in,
android.R.anim.fade_out);
SetupStats.addEvent(SetupStats.Categories.EXTERNAL_PAGE_LOAD,
SetupStats.Action.EXTERNAL_PAGE_LAUNCH,
SetupStats.Label.PAGE, SetupStats.Label.WIFI_SETUP);
mLoadingFragment.startActivityForResult(intent,
SetupWizardApp.REQUEST_CODE_SETUP_WIFI, options.toBundle());
}
}

View File

@@ -1,117 +0,0 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.ui;
import android.annotation.Nullable;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import com.android.setupwizard.navigationbar.SetupWizardNavBar;
import com.android.setupwizard.navigationbar.SetupWizardNavBar.NavigationBarListener;
import com.android.setupwizardlib.util.SystemBarHelper;
public abstract class BaseSetupWizardActivity extends Activity implements NavigationBarListener {
/* Logging */
public static final boolean LOGV = true;
public static final String TAG = BaseSetupWizardActivity.class.getSimpleName();
private SetupWizardNavBar mNavigationBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SystemBarHelper.hideSystemBars(getWindow());
}
@Override
public void onNavigationBarCreated(SetupWizardNavBar bar) {
mNavigationBar = bar;
bar.setUseImmersiveMode(true);
bar.getView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
view.requestApplyInsets();
}
});
}
protected void setBackDrawable(Drawable drawable) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setCompoundDrawables(drawable, null, null, null);
}
}
protected void setNextDrawable(Drawable drawable) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setCompoundDrawables(null, null, drawable, null);
}
}
protected void setBackAllowed(boolean allowed) {
// Enable / disable navigation bar back button
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setEnabled(allowed);
}
}
protected void setNextAllowed(boolean allowed) {
if (mNavigationBar != null) {
mNavigationBar.getNextButton().setEnabled(allowed);
}
}
protected void setNextText(int resId) {
if (mNavigationBar != null) {
mNavigationBar.getNextButton().setText(resId);
}
}
protected void setBackText(int resId) {
if (mNavigationBar != null) {
mNavigationBar.getBackButton().setText(resId);
}
}
protected void hideNextButton() {
if (mNavigationBar != null) {
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
final Button next = mNavigationBar.getNextButton();
next.startAnimation(fadeOut);
next.setVisibility(View.INVISIBLE);
}
}
protected void hideBackButton() {
if (mNavigationBar != null) {
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
final Button back = mNavigationBar.getBackButton();
back.startAnimation(fadeOut);
back.setVisibility(View.INVISIBLE);
}
}
}

View File

@@ -1,89 +0,0 @@
/*
* Copyright (C) 2015 The CyanogenMod 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.cyanogenmod.setupwizard.ui;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.cyanogenmod.setupwizard.R;
public class LoadingFragment extends SetupPageFragment {
private StartActivityForResultRunnable mStartActivityForResultRunnable;
private static final String TAG = "LoadingFragment";
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
if (isResumed()) {
super.startActivityForResult(intent, requestCode, options);
} else {
mStartActivityForResultRunnable =
new StartActivityForResultRunnable(this, intent, requestCode, options);
}
}
@Override
public void onResume() {
super.onResume();
if (mStartActivityForResultRunnable != null) {
mStartActivityForResultRunnable.run();
}
}
@Override
public void onPause() {
super.onPause();
mStartActivityForResultRunnable = null;
}
@Override
protected void initializePage() {}
@Override
protected int getLayoutResource() {
return R.layout.setup_loading_page;
}
private static class StartActivityForResultRunnable implements Runnable {
private final LoadingFragment mLoadingFragment;
private final Intent mIntent;
private final int mRequestCode;
private final Bundle mOptions;
private StartActivityForResultRunnable(LoadingFragment loadingFragment,
Intent intent, int requestCode, Bundle options) {
mLoadingFragment = loadingFragment;
mIntent = intent;
mRequestCode = requestCode;
mOptions = options;
}
@Override
public void run() {
try {
mLoadingFragment.startActivityForResult(mIntent, mRequestCode, mOptions);
}
catch(ActivityNotFoundException e) {
Log.e(TAG,"Activity not found to handle intent "+ mIntent.getDataString());
}
}
}
}

View File

@@ -1,114 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.ui;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.setup.Page;
import com.cyanogenmod.setupwizard.setup.SetupDataCallbacks;
public abstract class SetupPageFragment extends Fragment {
protected SetupDataCallbacks mCallbacks;
protected String mKey;
protected Page mPage;
protected View mRootView;
protected TextView mTitleView;
protected ImageView mIconView;
protected ViewGroup mHeaderView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
SetupStats.addEvent(SetupStats.Categories.PAGE_LOAD, SetupStats.Action.PAGE_LOADED,
mKey, String.valueOf(System.currentTimeMillis()));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRootView = inflater.inflate(getLayoutResource(), container, false);
mTitleView = (TextView) mRootView.findViewById(android.R.id.title);
mHeaderView = (ViewGroup) mRootView.findViewById(R.id.header);
mIconView = (ImageView) mRootView.findViewById(R.id.header_icon);
initializePage();
return mRootView;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Bundle args = getArguments();
mKey = args.getString(Page.KEY_PAGE_ARGUMENT);
if (mKey == null) {
throw new IllegalArgumentException("No KEY_PAGE_ARGUMENT given");
}
if (!(activity instanceof SetupDataCallbacks)) {
throw new ClassCastException("Activity implement SetupDataCallbacks");
}
mCallbacks = (SetupDataCallbacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
@Override
public void onResume() {
super.onResume();
mPage = mCallbacks.getPage(mKey);
if (mTitleView != null) {
mTitleView.setText(mPage.getTitleResId());
}
if (mIconView != null) {
int mResId = mPage.getIconResId();
if (mResId != -1) {
mIconView.setImageResource(mResId);
mIconView.setVisibility(View.VISIBLE);
}
}
mCallbacks.onPageLoaded(mPage);
getActivity().startPostponedEnterTransition();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// On low mem devices, this fragment might get destroyed by
// fragment manager while we are in another activity.
if (mPage == null) {
mPage = mCallbacks.getPage(mKey);
}
mPage.onActivityResult(requestCode, resultCode, data);
}
protected abstract void initializePage();
protected abstract int getLayoutResource();
}

View File

@@ -1,497 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.ui;
import android.animation.Animator;
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.android.setupwizardlib.util.SystemBarHelper;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import com.cyanogenmod.setupwizard.setup.CMSetupWizardData;
import com.cyanogenmod.setupwizard.setup.Page;
import com.cyanogenmod.setupwizard.setup.SetupDataCallbacks;
import com.cyanogenmod.setupwizard.util.EnableAccessibilityController;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import java.util.ArrayList;
import cyanogenmod.providers.CMSettings;
import cyanogenmod.themes.ThemeManager;
public class SetupWizardActivity extends Activity implements SetupDataCallbacks,
ThemeManager.ThemeChangeListener {
private static final String TAG = SetupWizardActivity.class.getSimpleName();
private static final String KEY_LAST_PAGE_TAG = "last_page_tag";
private View mRootView;
private View mButtonBar;
private Button mNextButton;
private Button mPrevButton;
private ImageView mReveal;
private ProgressBar mFinishingProgressBar;
private EnableAccessibilityController mEnableAccessibilityController;
private CMSetupWizardData mSetupData;
private final Handler mHandler = new Handler();
private volatile boolean mIsFinishing = false;
private static long sLaunchTime = 0;
private final ArrayList<Runnable> mFinishRunnables = new ArrayList<Runnable>();
private Intent mAfterFinishIntent;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final boolean isOwner = SetupWizardUtils.isOwner();
if (!isOwner) {
finish();
}
SystemBarHelper.hideSystemBars(getWindow());
if (sLaunchTime == 0) {
SetupStats.addEvent(SetupStats.Categories.APP_LAUNCH, TAG);
sLaunchTime = System.nanoTime();
}
setContentView(R.layout.setup_main);
mRootView = findViewById(R.id.root);
mReveal = (ImageView)mRootView.findViewById(R.id.reveal);
mButtonBar = findViewById(R.id.button_bar);
mFinishingProgressBar = (ProgressBar)findViewById(R.id.finishing_bar);
mSetupData = (CMSetupWizardData)getLastNonConfigurationInstance();
if (mSetupData == null) {
mSetupData = new CMSetupWizardData(getApplicationContext());
}
mNextButton = (Button) findViewById(R.id.next_button);
mPrevButton = (Button) findViewById(R.id.prev_button);
if (mSetupData.isFinished()) {
mNextButton.setVisibility(View.INVISIBLE);
mPrevButton.setVisibility(View.INVISIBLE);
}
mSetupData.registerListener(this);
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableButtonBar(false);
mSetupData.onNextPage();
}
});
mPrevButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableButtonBar(false);
mSetupData.onPreviousPage();
}
});
if (savedInstanceState == null) {
Page page = mSetupData.getCurrentPage();
page.doLoadAction(getFragmentManager(), Page.ACTION_NEXT);
}
if (savedInstanceState != null && savedInstanceState.containsKey("data")) {
mSetupData.load(savedInstanceState.getBundle("data"));
}
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPreferences.contains(KEY_LAST_PAGE_TAG)) {
final String lastPage = sharedPreferences.getString(KEY_LAST_PAGE_TAG,
mSetupData.getCurrentPage().getKey());
final boolean backupEnabled = (Settings.Secure.getInt(getContentResolver(),
Settings.Secure.BACKUP_AUTO_RESTORE, 0) == 1) ||
(Settings.Secure.getInt(getContentResolver(),
Settings.Secure.BACKUP_ENABLED, 0) == 1);
mSetupData.setCurrentPage(sharedPreferences.getString(KEY_LAST_PAGE_TAG,
mSetupData.getCurrentPage().getKey()));
Page page = mSetupData.getCurrentPage();
page.doLoadAction(getFragmentManager(), Page.ACTION_NEXT);
}
mEnableAccessibilityController =
EnableAccessibilityController.getInstance(getApplicationContext());
mRootView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean consumeIntercept = mEnableAccessibilityController.onInterceptTouchEvent(event);
boolean consumeTouch = mEnableAccessibilityController.onTouchEvent(event);
return consumeIntercept && consumeTouch;
}
});
registerReceiver(mSetupData, mSetupData.getIntentFilter());
}
@Override
protected void onResume() {
super.onResume();
if (isFinishing()) {
return;
}
if (mSetupData.isFinished()) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
finishSetup();
}
}, 500);
} else {
mSetupData.onResume();
onPageTreeChanged();
enableButtonBar(true);
}
}
@Override
protected void onPause() {
super.onPause();
if (mSetupData != null) {
mSetupData.onPause();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSetupData != null) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString(KEY_LAST_PAGE_TAG, mSetupData.getCurrentPage().getKey()).apply();
mSetupData.onDestroy();
mSetupData.unregisterListener(this);
unregisterReceiver(mSetupData);
}
}
@Override
public Object onRetainNonConfigurationInstance() {
return mSetupData;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBundle("data", mSetupData.save());
}
@Override
public void onBackPressed() {
if (!mSetupData.isFirstPage()) {
mSetupData.onPreviousPage();
}
}
@Override
public void onNextPage() {
Page page = mSetupData.getCurrentPage();
if (!isFinishing()) {
page.doLoadAction(getFragmentManager(), Page.ACTION_NEXT);
}
}
@Override
public void onPreviousPage() {
Page page = mSetupData.getCurrentPage();
if (!isFinishing()) {
page.doLoadAction(getFragmentManager(), Page.ACTION_PREVIOUS);
}
}
@Override
public void setCurrentPage(String key) {
Page page = mSetupData.getCurrentPage();
if (!isFinishing()) {
page.doLoadAction(getFragmentManager(), Page.ACTION_NEXT);
}
}
@Override
public void onPageLoaded(Page page) {
updateButtonBar();
enableButtonBar(true);
}
@Override
public void onPageTreeChanged() {
updateButtonBar();
}
private void enableButtonBar(boolean enabled) {
mNextButton.setEnabled(enabled);
mPrevButton.setEnabled(enabled);
}
private void updateButtonBar() {
Page page = mSetupData.getCurrentPage();
mButtonBar.setBackgroundColor(getColor(page.getButtonBarBackgroundColorId()));
mNextButton.setText(page.getNextButtonTitleResId());
if (page.getPrevButtonTitleResId() != -1) {
mPrevButton.setText(page.getPrevButtonTitleResId());
} else {
mPrevButton.setText("");
}
if (mSetupData.isFirstPage()) {
mPrevButton.setCompoundDrawables(null, null, null, null);
mPrevButton.setVisibility(SetupWizardUtils.hasTelephony(this) ?
View.VISIBLE : View.INVISIBLE);
} else {
mPrevButton.setCompoundDrawablesWithIntrinsicBounds(
getDrawable(R.drawable.ic_chevron_left_dark),
null, null, null);
}
final Resources resources = getResources();
mButtonBar.setBackgroundResource(R.color.button_bar_background);
mNextButton.setCompoundDrawablesWithIntrinsicBounds(null, null,
getDrawable(R.drawable.ic_chevron_right_dark), null);
mNextButton.setTextColor(resources.getColorStateList(R.color.button_bar_text));
mPrevButton.setTextColor(resources.getColorStateList(R.color.button_bar_text));
}
@Override
public Page getPage(String key) {
return mSetupData.getPage(key);
}
@Override
public Page getPage(int key) {
return mSetupData.getPage(key);
}
@Override
public boolean isCurrentPage(Page page) {
return mSetupData.isCurrentPage(page);
}
@Override
public void addFinishRunnable(Runnable runnable) {
mFinishRunnables.add(runnable);
}
@Override
public void onFinish() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
mNextButton.startAnimation(fadeOut);
mNextButton.setVisibility(View.INVISIBLE);
mPrevButton.startAnimation(fadeOut);
mPrevButton.setVisibility(View.INVISIBLE);
final SetupWizardApp setupWizardApp = (SetupWizardApp)getApplication();
setupWizardApp.enableCaptivePortalDetection();
Animation fadeIn = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
mFinishingProgressBar.setVisibility(View.VISIBLE);
mFinishingProgressBar.setIndeterminate(true);
mFinishingProgressBar.startAnimation(fadeIn);
final ThemeManager tm = ThemeManager.getInstance(this);
try {
tm.registerThemeChangeListener(this);
} catch (Exception e) {
Log.w(TAG, "ThemeChangeListener already registered");
}
mSetupData.finishPages();
}
@Override
public void onFinish(boolean isSuccess) {
if (isResumed()) {
mHandler.post(new Runnable() {
@Override
public void run() {
finishSetup();
}
});
}
}
@Override
public void onProgress(int progress) {
if (progress > 0) {
mFinishingProgressBar.setIndeterminate(false);
mFinishingProgressBar.setProgress(progress);
}
}
@Override
public void finishSetup() {
if (!mIsFinishing) {
SetupStats.addEvent(SetupStats.Categories.APP_FINISHED, TAG,
SetupStats.Label.TOTAL_TIME, String.valueOf(
System.nanoTime() - sLaunchTime));
final SetupWizardApp setupWizardApp = (SetupWizardApp)getApplication();
setupWizardApp.sendStickyBroadcastAsUser(
new Intent(SetupWizardApp.ACTION_FINISHED),
Binder.getCallingUserHandle());
mIsFinishing = true;
setupRevealImage();
}
}
@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.translucent_enter, R.anim.translucent_exit);
}
private void setupRevealImage() {
mFinishingProgressBar.setProgress(100);
Animation fadeOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
mFinishingProgressBar.startAnimation(fadeOut);
mFinishingProgressBar.setVisibility(View.INVISIBLE);
final Point p = new Point();
getWindowManager().getDefaultDisplay().getRealSize(p);
final WallpaperManager wallpaperManager =
WallpaperManager.getInstance(SetupWizardActivity.this);
wallpaperManager.forgetLoadedWallpaper();
final Bitmap wallpaper = wallpaperManager.getBitmap();
Bitmap cropped = null;
if (wallpaper != null) {
cropped = Bitmap.createBitmap(wallpaper, 0,
0, Math.min(p.x, wallpaper.getWidth()),
Math.min(p.y, wallpaper.getHeight()));
}
if (cropped != null) {
mReveal.setScaleType(ImageView.ScaleType.CENTER_CROP);
mReveal.setImageBitmap(cropped);
} else {
mReveal.setBackground(wallpaperManager
.getBuiltInDrawable(p.x, p.y, false, 0, 0));
}
animateOut();
}
private void animateOut() {
int cx = (mReveal.getLeft() + mReveal.getRight()) / 2;
int cy = (mReveal.getTop() + mReveal.getBottom()) / 2;
int finalRadius = Math.max(mReveal.getWidth(), mReveal.getHeight());
Animator anim =
ViewAnimationUtils.createCircularReveal(mReveal, cx, cy, 0, finalRadius);
anim.setDuration(900);
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mReveal.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
mHandler.post(new Runnable() {
@Override
public void run() {
finalizeSetup();
}
});
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
anim.start();
}
private void finalizeSetup() {
mFinishRunnables.add(new Runnable() {
@Override
public void run() {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 1);
CMSettings.Secure.putInt(getContentResolver(),
CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 1);
if (mEnableAccessibilityController != null) {
mEnableAccessibilityController.onDestroy();
}
final ThemeManager tm = ThemeManager.getInstance(SetupWizardActivity.this);
tm.unregisterThemeChangeListener(SetupWizardActivity.this);
SetupStats.sendEvents(SetupWizardActivity.this);
final WallpaperManager wallpaperManager =
WallpaperManager.getInstance(SetupWizardActivity.this);
wallpaperManager.forgetLoadedWallpaper();
}
});
new FinishTask(this, mFinishRunnables).execute();
}
private static class FinishTask extends AsyncTask<Void, Void, Boolean> {
private final SetupWizardActivity mActivity;
private final ArrayList<Runnable> mFinishRunnables;
public FinishTask(SetupWizardActivity activity,
ArrayList<Runnable> finishRunnables) {
mActivity = activity;
mFinishRunnables = finishRunnables;
}
@Override
protected Boolean doInBackground(Void... params) {
for (Runnable runnable : mFinishRunnables) {
runnable.run();
}
SetupWizardUtils.disableSetupWizard(mActivity);
return Boolean.TRUE;
}
@Override
protected void onPostExecute(Boolean aBoolean) {
if (mActivity.mAfterFinishIntent == null) {
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
mActivity.startActivity(intent);
} else {
mActivity.startActivity(mActivity.mAfterFinishIntent);
}
mActivity.finish();
}
}
/**
* Sets an intent to be started when the wizard finishes.
* By default, or null, it will go Home.
* @param intent Intent to start after wizard finishes.
*/
public void setFinishIntent(final Intent intent) {
mAfterFinishIntent = intent;
}
}

View File

@@ -39,7 +39,6 @@ import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
import com.android.internal.R;
import com.cyanogenmod.setupwizard.cmstats.SetupStats;
import java.util.ArrayList;
import java.util.Iterator;
@@ -284,8 +283,6 @@ public class EnableAccessibilityController {
// Turn on accessibility mode last.
Settings.Secure.putIntForUser(resolver, Settings.Secure.ACCESSIBILITY_ENABLED,
1, userId);
SetupStats.addEvent(SetupStats.Categories.SETTING_CHANGED,
"accessibility_enabled");
} else if (keyguardLocked) {
try {
mAccessibilityManager.temporaryEnableAccessibilityStateUntilKeyguardRemoved(

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.util;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.util.Log;
import com.cyanogenmod.setupwizard.SetupWizardApp;
public class NetworkMonitor {
public static final String TAG = NetworkMonitor.class.getSimpleName();
private static NetworkMonitor sInstance;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (LOGV) {
Log.v(TAG, intent.toString());
}
NetworkMonitor.this.updateNetworkStatus(context);
}
};
private Context mContext = null;
private boolean mNetworkConnected = false;
private NetworkInfo mNetworkInfo = null;
public static void initInstance(Context context) {
if (sInstance == null) {
sInstance = new NetworkMonitor(context.getApplicationContext());
}
}
public static NetworkMonitor getInstance() {
return sInstance;
}
public NetworkMonitor(Context context) {
mContext = context;
if (LOGV) {
Log.v(TAG, "Starting NetworkMonitor");
}
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
context.registerReceiver(mBroadcastReceiver, filter);
new Handler().post(new Runnable() {
public void run() {
updateNetworkStatus(mContext);
}
});
}
public boolean isNetworkConnected() {
if (LOGV) {
Log.v(TAG, "isNetworkConnected() returns " + mNetworkConnected);
}
return mNetworkConnected;
}
public boolean isWifiConnected() {
boolean wifiConnected = (!mNetworkConnected || mNetworkInfo == null) ?
false :
mNetworkInfo.getType() == 1;
if (LOGV) {
Log.v(TAG, "isWifiConnected() returns " + wifiConnected);
}
return wifiConnected;
}
public boolean checkIsNetworkConnected() {
updateNetworkStatus(mContext);
return isNetworkConnected();
}
private void onNetworkConnected(NetworkInfo ni) {
if (LOGV) {
Log.v(TAG, "onNetworkConnected()");
}
mNetworkConnected = true;
mNetworkInfo = ni;
}
private void onNetworkDisconnected() {
if (LOGV) {
Log.v(TAG, "onNetworkDisconnected()");
}
mNetworkConnected = false;
mNetworkInfo = null;
}
private boolean updateNetworkStatus(Context context) {
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
if (cm != null) {
NetworkInfo ni = cm.getActiveNetworkInfo();
boolean isConnected = ni != null ? ni.isConnected() : false;
if (isConnected && !mNetworkConnected) {
onNetworkConnected(ni);
} else if (!isConnected && mNetworkConnected) {
onNetworkDisconnected();
}
}
return mNetworkConnected;
}
}

View File

@@ -0,0 +1,487 @@
/*
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.util;
import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
import static android.telephony.PhoneStateListener.LISTEN_NONE;
import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE;
import static android.telephony.PhoneStateListener.LISTEN_SIGNAL_STRENGTHS;
import static android.telephony.ServiceState.STATE_EMERGENCY_ONLY;
import static android.telephony.ServiceState.STATE_IN_SERVICE;
import static android.telephony.ServiceState.STATE_OUT_OF_SERVICE;
import static android.telephony.ServiceState.STATE_POWER_OFF;
import static android.telephony.TelephonyManager.DATA_CONNECTED;
import static android.telephony.TelephonyManager.DATA_CONNECTING;
import static android.telephony.TelephonyManager.DATA_DISCONNECTED;
import static android.telephony.TelephonyManager.DATA_SUSPENDED;
import static android.telephony.TelephonyManager.DATA_UNKNOWN;
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
import static android.telephony.TelephonyManager.PHONE_TYPE_GSM;
import static android.telephony.TelephonyManager.PHONE_TYPE_NONE;
import static android.telephony.TelephonyManager.PHONE_TYPE_SIP;
import static android.telephony.TelephonyManager.SIM_STATE_ABSENT;
import static android.telephony.TelephonyManager.SIM_STATE_CARD_IO_ERROR;
import static android.telephony.TelephonyManager.SIM_STATE_NETWORK_LOCKED;
import static android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED;
import static android.telephony.TelephonyManager.SIM_STATE_PUK_REQUIRED;
import static android.telephony.TelephonyManager.SIM_STATE_READY;
import static android.telephony.TelephonyManager.SIM_STATE_UNKNOWN;
import static com.android.internal.telephony.PhoneConstants.LTE_ON_CDMA_TRUE;
import static com.android.internal.telephony.PhoneConstants.LTE_ON_CDMA_UNKNOWN;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemProperties;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
public class PhoneMonitor {
public static final String TAG = PhoneMonitor.class.getSimpleName();
private static PhoneMonitor sInstance;
private Context mContext;
private TelephonyManager mTelephony;
private SubscriptionManager mSubscriptionManager;
private ArrayList<SubscriptionStateListener> mListeners = new ArrayList<>();
private SparseArray<SubscriptionStateTracker> mTrackers = new SparseArray<>();
private int mChangingToDataSubId = -1;
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
final int sub = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1);
final int state = mTelephony.getSimState(sub);
simStateChanged(sub, state);
} else if (intent.getAction()
.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
ddsHasChanged(intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, -1));
}
}
};
private class SubscriptionStateTracker extends PhoneStateListener {
private ServiceState mServiceState;
private int mSubId = -1;
public SubscriptionStateTracker(int subId) {
super(subId);
mSubId = subId;
}
public void onServiceStateChanged(ServiceState serviceState) {
mServiceState = serviceState;
if (LOGV) {
logPhoneState("onServiceStateChanged state=\"" + serviceState + "\" ");
}
for (SubscriptionStateListener listener : mListeners) {
listener.onServiceStateChanged(mSubId, serviceState);
}
}
public void onDataConnectionStateChanged(int state, int networkType) {
for (SubscriptionStateListener listener : mListeners) {
listener.onDataConnectionStateChanged(mSubId, state, networkType);
}
}
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
for (SubscriptionStateListener listener : mListeners) {
listener.onSignalStrengthsChanged(mSubId, signalStrength);
}
}
}
private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
new OnSubscriptionsChangedListener() {
public void onSubscriptionsChanged() {
if (LOGV) {
Log.d(TAG, "Subscriptions changed");
}
super.onSubscriptionsChanged();
updatePhoneStateTrackers();
}
};
public static void initInstance(Context context) {
if (sInstance == null) {
sInstance = new PhoneMonitor(context.getApplicationContext());
}
}
public static void onSetupFinished() {
if (sInstance != null) {
sInstance.mContext.unregisterReceiver(sInstance.mIntentReceiver);
}
}
public static PhoneMonitor getInstance() {
return sInstance;
}
public PhoneMonitor(Context context) {
mContext = context;
if (LOGV) {
Log.v(TAG, "Starting PhoneMonitor");
}
mTelephony = mContext.getSystemService(TelephonyManager.class);
if (mTelephony != null) {
mSubscriptionManager = SubscriptionManager.from(mContext);
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
updatePhoneStateTrackers();
}
// Register for DDS changes
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
context.registerReceiver(mIntentReceiver, filter, null, null);
}
private void updatePhoneStateTrackers() {
int i = 0;
int[] subIds = mSubscriptionManager.getActiveSubscriptionIdList();
HashSet<Integer> subIdSet = new HashSet(Arrays.asList(subIds));
if (LOGV) {
Log.v(TAG, "Register PhoneStateListeners for " + subIdSet);
}
for (int i2 = 0; i2 < mTrackers.size(); i2++) {
if (!subIdSet.contains(Integer.valueOf(mTrackers.keyAt(i2)))) {
mTelephony.listen(mTrackers.valueAt(i2), LISTEN_NONE);
mTrackers.removeAt(i2);
}
}
int length = subIds.length;
while (i < length) {
int subId = subIds[i];
if (mTrackers.indexOfKey(subId) < 0) {
SubscriptionStateTracker tracker = new SubscriptionStateTracker(subId);
mTrackers.put(subId, tracker);
mTelephony.listen(tracker, LISTEN_SERVICE_STATE
| LISTEN_SIGNAL_STRENGTHS
| LISTEN_DATA_CONNECTION_STATE);
}
i++;
}
}
public void addListener(SubscriptionStateListener listener) {
mListeners.add(listener);
}
public void removeListener(SubscriptionStateListener listener) {
mListeners.remove(listener);
}
public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
return mSubscriptionManager.getActiveSubscriptionInfo(subId);
}
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
return mSubscriptionManager.getActiveSubscriptionInfoList();
}
public String getSimOperatorName(int subId) {
return mTelephony.getSimOperatorName(subId);
}
public String getNetworkOperatorName(int subId) {
return mTelephony.getNetworkOperatorName(subId);
}
public ServiceState getServiceStateForSubscriber(int subId) {
return mTelephony.getServiceStateForSubscriber(subId);
}
public void changeDataSub(int subId) {
if (LOGV) {
Log.v(TAG, "changeDataSub{" +
"subId='" + subId + '\'' +
", mChangingToDataSubId=" + mChangingToDataSubId +
'}');
}
if (mChangingToDataSubId != subId) {
mSubscriptionManager.setDefaultDataSubId(subId);
for (SubscriptionStateListener subscriptionStateListener : mListeners) {
subscriptionStateListener
.onDefaultDataSubscriptionChangeRequested(mChangingToDataSubId, subId);
}
mChangingToDataSubId = subId;
}
}
private void ddsHasChanged(int subId) {
if (subId > -1) {
for (SubscriptionStateListener subscriptionStateListener : mListeners) {
subscriptionStateListener.onDefaultDataSubscriptionChanged(subId);
}
}
}
private void simStateChanged(int subId, int simState) {
if (LOGV) {
Log.v(TAG,
"simStateChanged(" + subId + ", " + simState + ")");
}
for (SubscriptionStateListener subscriptionStateListener : mListeners) {
subscriptionStateListener.onSimStateChanged(subId, simState);
}
}
public boolean simMissing() {
if (mTelephony == null) {
return false;
}
List<SubscriptionInfo> subs = mSubscriptionManager.getActiveSubscriptionInfoList();
if (subs != null) {
for (SubscriptionInfo sub : subs) {
int simState = mTelephony.getSimState(sub.getSimSlotIndex());
if (LOGV) {
Log.v(TAG, "getSimState(" + sub.getSubscriptionId() + ") == " + simState);
}
int subId = sub.getSubscriptionId();
boolean isGsm = isGSM(subId);
boolean isLte = isLte(subId);
if ((isGsm || isLte) && simState != 1) {
return false;
}
}
}
return true;
}
// We only care that each slot has a sim
public boolean allSimsInserted() {
int simSlotCount = mTelephony.getSimCount();
for (int i = 0; i < simSlotCount; i++) {
int state = mTelephony.getSimState(i);
if (state == TelephonyManager.SIM_STATE_ABSENT) {
return false;
}
}
return simSlotCount == mSubscriptionManager.getActiveSubscriptionInfoCount();
}
public boolean isGSM(int subId) {
return mTelephony.getCurrentPhoneType(subId) == PHONE_TYPE_GSM;
}
public boolean isLte(int subId) {
return getLteOnCdmaMode(subId) == LTE_ON_CDMA_TRUE;
}
public int getLteOnCdmaMode(int subId) {
if (mTelephony == null || mTelephony.getLteOnCdmaMode(subId) == LTE_ON_CDMA_UNKNOWN) {
return SystemProperties.getInt("telephony.lteOnCdmaDevice", LTE_ON_CDMA_UNKNOWN);
}
return mTelephony.getLteOnCdmaMode(subId);
}
private void logPhoneState(String prefix) {
if (LOGV) {
Log.v(TAG, prefix + getPhoneState());
}
}
private String getPhoneTypeName() {
return getPhoneTypeName(mTelephony != null ? mTelephony.getCurrentPhoneType() : -1);
}
private int getMcc() {
return mContext.getResources().getConfiguration().mcc;
}
private int getMnc() {
return mContext.getResources().getConfiguration().mnc;
}
private String getPhoneTypeName(int phoneType) {
StringBuilder sb = new StringBuilder();
switch (phoneType) {
case PHONE_TYPE_NONE:
sb.append("PHONE_TYPE_NONE");
break;
case PHONE_TYPE_GSM:
sb.append("PHONE_TYPE_GSM");
break;
case PHONE_TYPE_CDMA:
sb.append("PHONE_TYPE_CDMA");
break;
case PHONE_TYPE_SIP:
sb.append("PHONE_TYPE_SIP");
break;
}
sb.append("(").append(phoneType).append(")");
return sb.toString();
}
private String getNetworkTypeName() {
return mTelephony != null ? mTelephony.getNetworkTypeName() : "";
}
private String getSubscriptionSimStateName(int subId) {
SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId);
if (subInfo == null) {
return "SIM_STATE_UNKNOWN";
}
return mTelephony != null ?
getSimStateName(mTelephony.getSimState(subInfo.getSimSlotIndex())) : "";
}
private String getDataStateName() {
return mTelephony != null ? getDataStateName(mTelephony.getDataState()) : "";
}
private String getDataStateName(int dataState) {
StringBuilder sb = new StringBuilder();
switch (dataState) {
case DATA_UNKNOWN:
sb.append("DATA_UNKNOWN");
break;
case DATA_DISCONNECTED:
sb.append("DATA_DISCONNECTED");
break;
case DATA_CONNECTING:
sb.append("DATA_CONNECTING");
break;
case DATA_CONNECTED:
sb.append("DATA_CONNECTED");
break;
case DATA_SUSPENDED:
sb.append("DATA_SUSPENDED");
break;
}
sb.append("(").append(dataState).append(")");
return sb.toString();
}
private String getSimStateName(int simState) {
StringBuilder sb = new StringBuilder();
switch (simState) {
case SIM_STATE_UNKNOWN:
sb.append("SIM_STATE_UNKNOWN");
break;
case SIM_STATE_ABSENT:
sb.append("SIM_STATE_ABSENT");
break;
case SIM_STATE_PIN_REQUIRED:
sb.append("SIM_STATE_PIN_REQUIRED");
break;
case SIM_STATE_PUK_REQUIRED:
sb.append("SIM_STATE_PUK_REQUIRED");
break;
case SIM_STATE_NETWORK_LOCKED:
sb.append("SIM_STATE_NETWORK_LOCKED");
break;
case SIM_STATE_READY:
sb.append("SIM_STATE_READY");
break;
case SIM_STATE_CARD_IO_ERROR:
sb.append("SIM_STATE_CARD_IO_ERROR");
break;
}
sb.append("(").append(simState).append(")");
return sb.toString();
}
private String getVoiceServiceStateName(int subId) {
return getServiceStateName(getVoiceRegState(subId));
}
private String getDataServiceStateName(int subId) {
return getServiceStateName(getDataRegState(subId));
}
private int getVoiceRegState(int subId) {
SubscriptionStateTracker tracker = mTrackers.get(subId);
ServiceState serviceState = tracker != null ? tracker.mServiceState : null;
return serviceState != null ? serviceState.getVoiceRegState() : -1;
}
private int getDataRegState(int subId) {
SubscriptionStateTracker tracker = mTrackers.get(subId);
ServiceState serviceState = tracker != null ? tracker.mServiceState : null;
return serviceState != null ? serviceState.getDataRegState() : -1;
}
private String getServiceStateName(int serviceState) {
StringBuilder sb = new StringBuilder();
switch (serviceState) {
case STATE_IN_SERVICE:
sb.append("STATE_IN_SERVICE");
break;
case STATE_OUT_OF_SERVICE:
sb.append("STATE_OUT_OF_SERVICE");
break;
case STATE_EMERGENCY_ONLY:
sb.append("STATE_EMERGENCY_ONLY");
break;
case STATE_POWER_OFF:
sb.append("STATE_POWER_OFF");
break;
}
sb.append("(").append(serviceState).append(")");
return sb.toString();
}
private String getPhoneState() {
StringBuilder states = new StringBuilder();
for (int subId : mSubscriptionManager.getActiveSubscriptionIdList()) {
states.append(" ").append(getPhoneState(subId));
}
return getPhoneTypeName() + " \"" + getNetworkTypeName() + "\"" + " mcc" + getMcc() +
"mnc" + getMnc() + " " + getDataStateName() + " " + states.toString();
}
private String getPhoneState(int subId) {
return "{ " + getSubscriptionSimStateName(subId) + " Voice:"
+ getVoiceServiceStateName(subId)
+ " Data:" + getDataServiceStateName(subId) + " }";
}
public interface SubscriptionStateListener {
void onServiceStateChanged(int subId, ServiceState serviceState);
void onDataConnectionStateChanged(int subId, int state, int networkType);
void onDefaultDataSubscriptionChanged(int subId);
void onDefaultDataSubscriptionChangeRequested(int currentSubId, int newSubId);
void onSignalStrengthsChanged(int subId, SignalStrength signalStrength);
void onSimStateChanged(int subId, int simState);
}
}

View File

@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,66 +17,71 @@
package com.cyanogenmod.setupwizard.util;
import android.accounts.AccountManager;
import android.app.AppGlobals;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
import static android.app.StatusBarManager.DISABLE_SEARCH;
import static android.content.Context.MODE_PRIVATE;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.DONT_KILL_APP;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.content.pm.PackageManager.GET_RECEIVERS;
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.res.ThemeConfig.SYSTEM_DEFAULT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.KEY_DETECT_CAPTIVE_PORTAL;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.hardware.fingerprint.FingerprintManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.UserManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
/*import com.android.internal.os.IKillSwitchService;*/
import com.cyanogenmod.setupwizard.BluetoothSetupActivity;
import com.cyanogenmod.setupwizard.ChooseDataSimActivity;
import com.cyanogenmod.setupwizard.FingerprintActivity;
import com.cyanogenmod.setupwizard.MobileDataActivity;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.SimMissingActivity;
import com.cyanogenmod.setupwizard.WifiSetupActivity;
import com.cyanogenmod.setupwizard.wizardmanager.WizardManager;
import org.cyanogenmod.internal.util.PackageManagerUtils;
import java.util.ArrayList;
import java.util.List;
import cyanogenmod.providers.CMSettings;
import static android.content.res.ThemeConfig.SYSTEM_DEFAULT;
public class SetupWizardUtils {
private static final String TAG = SetupWizardUtils.class.getSimpleName();
public static final String GOOGLE_SETUPWIZARD_PACKAGE = "com.google.android.setupwizard";
private SetupWizardUtils(){}
public static void tryEnablingWifi(Context context) {
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
}
public static boolean isNetworkConnected(Context context) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
public static boolean isWifiConnected(Context context) {
ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifi != null && mWifi.isConnected();
public static SharedPreferences getPrefs(Context context) {
return context.getSharedPreferences("SetupWizardPrefs", MODE_PRIVATE);
}
public static boolean isMobileDataEnabled(Context context) {
try {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
TelephonyManager tm = context.getSystemService(TelephonyManager.class);
return tm.getDataEnabled();
} catch (Exception e) {
return false;
@@ -83,8 +89,7 @@ public class SetupWizardUtils {
}
public static void setMobileDataEnabled(Context context, boolean enabled) {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
TelephonyManager tm = context.getSystemService(TelephonyManager.class);
if (tm.isMultiSimEnabled()) {
int phoneId = SubscriptionManager.from(context).getDefaultDataPhoneId();
android.provider.Settings.Global.putInt(context.getContentResolver(),
@@ -114,65 +119,6 @@ public class SetupWizardUtils {
return tm.isMultiSimEnabled();
}
public static boolean isGSMPhone(Context context) {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int phoneType = tm.getPhoneType();
return phoneType == TelephonyManager.PHONE_TYPE_GSM;
}
public static boolean isSimMissing(Context context) {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
int simCount = SubscriptionManager.from(context).getDefaultDataPhoneId();
for (int i = 0; i < simCount; i++) {
int simState = tm.getSimState(i);
if (simState != TelephonyManager.SIM_STATE_ABSENT &&
simState != TelephonyManager.SIM_STATE_UNKNOWN) {
return false;
}
}
return true;
}
public static boolean isDeviceLocked() {
/* IBinder b = ServiceManager.getService(Context.KILLSWITCH_SERVICE);
IKillSwitchService service = IKillSwitchService.Stub.asInterface(b);
if (service != null) {
try {
return service.isDeviceLocked();
} catch (Exception e) {
// silently fail
}
}*/
return false;
}
public static boolean frpEnabled(Context context) {
final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
return pdbManager != null
&& pdbManager.getDataBlockSize() > 0
&& !pdbManager.getOemUnlockEnabled();
}
public static boolean hasKillSwitch() {
/* IBinder b = ServiceManager.getService(Context.KILLSWITCH_SERVICE);
IKillSwitchService service = IKillSwitchService.Stub.asInterface(b);
if (service != null) {
try {
return service.hasKillSwitch();
} catch (Exception e) {
// silently fail
}
} */
return false;
}
public static boolean hasAuthorized() {
return ((SetupWizardApp) AppGlobals.getInitialApplication()).isAuthorized();
}
public static boolean isRadioReady(Context context, ServiceState state) {
final SetupWizardApp setupWizardApp = (SetupWizardApp)context.getApplicationContext();
if (setupWizardApp.isRadioReady()) {
@@ -186,54 +132,77 @@ public class SetupWizardUtils {
}
public static boolean isGuestUser(Context context) {
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
return userManager.isGuestUser();
public static boolean isOwner() {
return UserHandle.myUserId() == 0;
}
public static boolean isOwner() {
return Binder.getCallingUserHandle().isOwner();
public static void disableCaptivePortalDetection(Context context) {
Settings.Global.putInt(context.getContentResolver(), KEY_DETECT_CAPTIVE_PORTAL, 0);
}
public static void enableCaptivePortalDetection(Context context) {
Settings.Global.putInt(context.getContentResolver(), KEY_DETECT_CAPTIVE_PORTAL, 1);
}
public static void disableStatusBar(Context context) {
StatusBarManager statusBarManager = context.getSystemService(StatusBarManager.class);
if (statusBarManager != null) {
statusBarManager.disable(DISABLE_NOTIFICATION_ALERTS | DISABLE_SEARCH
);
} else {
Log.w(SetupWizardApp.TAG,
"Skip disabling notfications - could not get StatusBarManager");
}
}
public static void enableStatusBar(Context context) {
StatusBarManager statusBarManager = context.getSystemService(StatusBarManager.class);
if(statusBarManager != null) {
Log.i(SetupWizardApp.TAG, "Enabling notfications - StatusBarManager");
statusBarManager.disable(DISABLE_NONE);
} else {
Log.i(SetupWizardApp.TAG, "Skip enabling notfications - StatusBarManager is null");
}
}
public static boolean hasGMS(Context context) {
return GooglePlayServicesUtil.isGooglePlayServicesAvailable(context) !=
ConnectionResult.SERVICE_MISSING;
}
public static boolean accountExists(Context context, String accountType) {
return AccountManager.get(context).getAccountsByType(accountType).length > 0;
if (PackageManagerUtils
.isAppInstalled(context, "com.google.android.gms")) {
PackageManager packageManager = context.getPackageManager();
if (LOGV) {
Log.v(TAG, "com.google.android.setupwizard state =" + packageManager
.getApplicationEnabledSetting("com.google.android.setupwizard"));
}
return packageManager
.getApplicationEnabledSetting("com.google.android.setupwizard") !=
COMPONENT_ENABLED_STATE_DISABLED;
}
return false;
}
public static boolean isPackageInstalled(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
pm.getPackageInfo(packageName, GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public static void disableSetupWizard(Context context) {
disableComponent(context, context.getPackageName(),
SetupWizardActivity.class.getName());
disableComponent(context, context.getPackageName(),
"com.cyanogenmod.setupwizard.ui.WelcomeActivity");
disableComponent(context, context.getPackageName(),
"com.cyanogenmod.setupwizard.ui.LocaleActivity");
disableComponent(context, context.getPackageName(),
"com.cyanogenmod.setupwizard.ui.LineageSettingsActivity");
disableComponent(context, context.getPackageName(),
"com.cyanogenmod.setupwizard.ui.FinishActivity");
}
public static void finishSetupWizard(Context context) {
ContentResolver contentResolver = context.getContentResolver();
Settings.Global.putInt(contentResolver,
Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(contentResolver,
Settings.Secure.USER_SETUP_COMPLETE, 1);
private static void disableComponent(Context context, String packageName, String name) {
disableComponent(context, new ComponentName(packageName, name));
}
private static void disableComponent(Context context, ComponentName component) {
context.getPackageManager().setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
disableComponent(context, WizardManager.class);
disableHome(context);
context.sendStickyBroadcastAsUser(
new Intent(SetupWizardApp.ACTION_FINISHED),
Binder.getCallingUserHandle());
disableComponentSets(context, GET_RECEIVERS | GET_SERVICES);
}
public static boolean hasLeanback(Context context) {
@@ -265,6 +234,121 @@ public class SetupWizardUtils {
return SYSTEM_DEFAULT;
}
public static void disableComponentsForMissingFeatures(Context context) {
if (!hasLeanback(context)) {
disableComponent(context, BluetoothSetupActivity.class);
}
if (!hasFingerprint(context)) {
disableComponent(context, FingerprintActivity.class);
}
if (!hasTelephony(context)) {
disableComponent(context, MobileDataActivity.class);
disableComponent(context, SimMissingActivity.class);
disableComponent(context, ChooseDataSimActivity.class);
} else if (!SetupWizardUtils.isMultiSimDevice(context)) {
disableComponent(context, ChooseDataSimActivity.class);
}
if (!SetupWizardUtils.hasWifi(context)) {
disableComponent(context, WifiSetupActivity.class);
}
}
public static void disableComponentsForGMS(Context context) {
disableComponent(context, WizardManager.class);
disableHome(context);
}
public static void disableHome(Context context) {
ComponentName homeComponent = getHomeComponent(context);
if (homeComponent != null) {
setComponentEnabledState(context, homeComponent, COMPONENT_ENABLED_STATE_DISABLED);
} else {
Log.w(TAG, "Home component not found. Skipping.");
}
}
public static ComponentName getHomeComponent(Context context) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
intent.setPackage(context.getPackageName());
ComponentName comp = intent.resolveActivity(context.getPackageManager());
if (SetupWizardApp.LOGV) {
Log.v(TAG, "resolveActivity for intent=" + intent + " returns " + comp);
}
return comp;
}
public static void disableComponentSets(Context context, int flags) {
setComponentListEnabledState(context, getComponentSets(context, flags),
COMPONENT_ENABLED_STATE_DISABLED);
}
public static void disableComponent(Context context, Class cls) {
setComponentEnabledState(context, new ComponentName(context, cls),
COMPONENT_ENABLED_STATE_DISABLED);
}
public static void enableComponent(Context context, Class<?> cls) {
setComponentEnabledState(context, new ComponentName(context, cls),
COMPONENT_ENABLED_STATE_ENABLED);
}
public static void resetComponentSets(Context context, int flags) {
setComponentListEnabledState(context, getComponentSets(context, flags),
COMPONENT_ENABLED_STATE_DEFAULT);
}
public static void resetComponent(Context context, Class<?> cls) {
setComponentEnabledState(context, new ComponentName(context, cls),
COMPONENT_ENABLED_STATE_DEFAULT);
}
public static void setComponentEnabledState(Context context, ComponentName componentName,
int enabledState) {
context.getPackageManager().setComponentEnabledSetting(componentName,
enabledState, DONT_KILL_APP);
}
public static void setComponentListEnabledState(Context context,
List<ComponentName> componentNames, int enabledState) {
for (ComponentName componentName : componentNames) {
setComponentEnabledState(context, componentName, enabledState);
}
}
public static List<ComponentName> getComponentSets(Context context, int flags) {
int i = 0;
List<ComponentName> componentNames = new ArrayList();
try {
PackageInfo allInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), flags);
if (allInfo != null) {
if (allInfo.activities != null && (flags & GET_ACTIVITIES) != 0) {
for (ComponentInfo info : allInfo.activities) {
componentNames.add(new ComponentName(context, info.name));
}
}
if (allInfo.receivers != null && (flags & GET_RECEIVERS) != 0) {
for (ComponentInfo info2 : allInfo.receivers) {
componentNames.add(new ComponentName(context, info2.name));
}
}
if (allInfo.services != null && (flags & GET_SERVICES) != 0) {
ServiceInfo[] serviceInfoArr = allInfo.services;
int length = serviceInfoArr.length;
while (i < length) {
componentNames.add(new ComponentName(context, serviceInfoArr[i].name));
i++;
}
}
}
} catch (PackageManager.NameNotFoundException e) {
}
return componentNames;
}
public static final ComponentName mTvwifisettingsActivity =
new ComponentName("com.android.tv.settings",
"com.android.tv.settings.connectivity.setup.WifiSetupActivity");

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui;
package com.cyanogenmod.setupwizard.widget;
import com.cyanogenmod.setupwizard.R;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.cyanogenmod.setupwizard.ui.widget;
package com.cyanogenmod.setupwizard.widget;
import android.content.Context;
import android.content.res.TypedArray;

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.wizardmanager;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.net.URISyntaxException;
public class WizardAction implements Parcelable {
private static final String TAG = "WizardAction";
private final String mId;
private final String mUri;
private final WizardTransitions mTransitions;
public WizardAction(String id, String uri, WizardTransitions transitions) {
if (transitions == null) {
throw new IllegalArgumentException("WizardTransitions cannot be null");
}
mId = id;
mUri = uri;
mTransitions = transitions;
}
public String getId() {
return mId;
}
public String getUri() {
return mUri;
}
public Intent getIntent() {
Intent intent = null;
try {
intent = Intent.parseUri(mUri, FLAG_GRANT_READ_URI_PERMISSION);
} catch(URISyntaxException e) {
Log.e(TAG, "Bad URI: " + mUri);
}
return intent;
}
public String getNextAction(int resultCode) {
return mTransitions.getAction(resultCode);
}
@Override
public String toString() {
return "WizardAction{" +
"mId='" + mId + '\'' +
", mUri='" + mUri + '\'' +
", mTransitions=" + mTransitions +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof WizardAction)) return false;
WizardAction that = (WizardAction) o;
if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false;
if (mUri != null ? !mUri.equals(that.mUri) : that.mUri != null) return false;
return mTransitions != null ?
mTransitions.equals(that.mTransitions) :
that.mTransitions == null;
}
@Override
public int hashCode() {
int result = mId != null ? mId.hashCode() : 0;
result = 31 * result + (mUri != null ? mUri.hashCode() : 0);
result = 31 * result + (mTransitions != null ? mTransitions.hashCode() : 0);
return result;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mUri);
dest.writeString(mId);
dest.writeParcelable(mTransitions, flags);
}
public static final Creator<WizardAction> CREATOR = new Creator<WizardAction>() {
public WizardAction createFromParcel(Parcel source) {
return new WizardAction(source.readString(),
source.readString(),
source.readParcelable(WizardTransitions.class.getClassLoader()));
}
public WizardAction[] newArray(int size) {
return new WizardAction[size];
}
};
private static void parseResult(WizardTransitions transitions, XmlPullParser parser) {
String resultCode = parser.getAttributeValue(WizardScript.WIZARD_SCRIPT_NAMESPACE,
WizardScript.ATTR_RESULT_CODE);
String action = parser.getAttributeValue(WizardScript.WIZARD_SCRIPT_NAMESPACE,
WizardScript.ATTR_ACTION);
if (LOGV) {
Log.v(TAG, "parseResult{" +
"resultCode='" + resultCode + '\'' +
", action=" + action +
'}');
}
if (resultCode == null) {
transitions.setDefaultAction(action);
} else {
transitions.put(Integer.valueOf(resultCode).intValue(), action);
}
}
public static WizardAction parseWizardAction(XmlPullParser parser) throws XmlPullParserException,
IOException {
String id = parser.getAttributeValue(null, WizardScript.ATTR_ID);
String uri = parser.getAttributeValue(WizardScript.WIZARD_SCRIPT_NAMESPACE,
WizardScript.ATTR_URI);
WizardTransitions transitions = new WizardTransitions();
if (id == null) {
throw new XmlPullParserException("WizardAction must define an id");
}
if (uri == null) {
throw new XmlPullParserException("WizardAction must define an intent URI");
}
if (LOGV) {
Log.v(TAG, "parseWizardAction{" +
"id='" + id + '\'' +
", uri=" + uri +
'}');
}
int type;
final int depth = parser.getDepth();
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
if (!(type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT)) {
if (parser.getName().equals(WizardScript.TAG_RESULT)) {
parseResult(transitions, parser);
} else {
XmlUtils.skipCurrentTag(parser);
}
}
}
return new WizardAction(id, uri, transitions);
}
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.wizardmanager;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_LOAD;
import static com.cyanogenmod.setupwizard.SetupWizardApp.ACTION_NEXT;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_ACTION_ID;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_FIRST_RUN;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_RESULT_CODE;
import static com.cyanogenmod.setupwizard.SetupWizardApp.EXTRA_SCRIPT_URI;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import com.android.setupwizardlib.util.ResultCodes;
import com.android.setupwizardlib.util.WizardManagerHelper;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import java.util.HashMap;
public class WizardManager extends Activity {
private static final String TAG = WizardManager.class.getSimpleName();
private static HashMap<String, WizardScript> sWizardScripts = new HashMap();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (LOGV) {
Log.v(TAG, "onCreate savedInstanceState=" + savedInstanceState);
}
Intent intent = this.getIntent();
if (intent != null) {
String action = intent.getAction();
int resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, 0);
String scriptUri = intent.getStringExtra(EXTRA_SCRIPT_URI);
String actionId = intent.getStringExtra(EXTRA_ACTION_ID);
if (LOGV) {
Log.v(TAG, " action=" + action + " resultCode=" + resultCode + " scriptUri="
+ scriptUri + " actionId=" + actionId + " extras=" + intent.getExtras());
}
if (ACTION_LOAD.equals(action)) {
load(scriptUri, intent);
finish();
return;
}
if (ACTION_NEXT.equals(action)) {
next(scriptUri, actionId, resultCode, intent);
finish();
return;
}
Log.e(TAG, "ERROR: Unknown action");
} else {
Log.e(TAG, "ERROR: Intent not available");
}
finish();
}
private void addExtras(Intent intent) {
intent.putExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, true);
intent.putExtra(EXTRA_FIRST_RUN, true);
intent.putExtra(WizardManagerHelper.EXTRA_THEME, WizardManagerHelper.THEME_MATERIAL_LIGHT);
}
private void doAction(String scriptUri, WizardAction action, Intent extras) {
Intent intent = action.getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if(LOGV) {
Log.v(TAG, "doAction scriptUri=" + scriptUri + " extras=" + extras
+ " intent=" + intent + " extras2=" + intent.getExtras() + " action=" + action);
}
addExtras(intent);
if(extras != null) {
intent.putExtras(extras);
}
intent.putExtra(EXTRA_SCRIPT_URI, scriptUri);
intent.putExtra(EXTRA_ACTION_ID, action.getId());
startActivity(intent);
}
private void load(String scriptUri, Intent extras) {
WizardScript wizardScript = getWizardScript(this, scriptUri);
WizardAction wizardAction;
for(wizardAction = wizardScript.getFirstAction();
wizardAction != null;
wizardAction = wizardScript.getNextAction(wizardAction.getId(),
ResultCodes.RESULT_ACTIVITY_NOT_FOUND)) {
if (isActionAvailable(this, wizardAction)) {
break;
}
if(LOGV) {
Log.v(TAG, "load action not available " + wizardAction);
}
}
if (wizardAction != null) {
doAction(scriptUri, wizardAction, extras);
} else {
Log.e(TAG, "load could not resolve first action scriptUri=" +
scriptUri + " actionId=" + wizardScript.getFirstActionId());
exit(scriptUri);
}
}
private void next(String scriptUri, String actionId, int resultCode, Intent extras) {
if(LOGV) {
Log.v(TAG, "next actionId=" + actionId + " resultCode=" + resultCode);
}
WizardAction wizardAction = checkNextAction(this, scriptUri,
actionId, resultCode);
if (wizardAction != null) {
doAction(scriptUri, wizardAction, extras);
} else {
exit(scriptUri);
}
}
private void exit(String scriptUri) {
if(LOGV) {
Log.v(TAG, "exit scriptUri=" + scriptUri);
}
WizardManager.sWizardScripts.remove(scriptUri);
SetupWizardUtils.disableComponent(this, WizardManager.class);
}
private static WizardAction checkNextAction(Context context, String scriptUri, String actionId,
int resultCode) {
if(LOGV) {
Log.v(TAG, "checkNextAction scriptUri=" + scriptUri + " actionId="
+ actionId + " resultCode=" + resultCode);
}
WizardScript wizardScript = getWizardScript(context, scriptUri);
WizardAction wizardAction;
for ( wizardAction = wizardScript.getNextAction(actionId, resultCode);
wizardAction != null;
wizardAction = wizardScript.getNextAction(wizardAction.getId(),
ResultCodes.RESULT_ACTIVITY_NOT_FOUND)) {
if (WizardManager.isActionAvailable(context, wizardAction)) {
break;
}
if(LOGV) {
Log.v(TAG, "checkNextAction action not available " + wizardAction);
}
}
if (LOGV) {
Log.v(TAG, "checkNextAction action=" + wizardAction);
}
return wizardAction;
}
private static boolean isActionAvailable(Context context, WizardAction action) {
return isIntentAvailable(context, action.getIntent());
}
private static boolean isIntentAvailable(Context context, Intent intent) {
if (context.getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY).size() > 0) {
return true;
}
return false;
}
private static WizardScript getWizardScript(Context context, String scriptUri) {
WizardScript wizardScript = sWizardScripts.get(scriptUri);
if (wizardScript == null) {
wizardScript = WizardScript.loadFromUri(context, scriptUri);
sWizardScripts.put(scriptUri, wizardScript);
}
return wizardScript;
}
}

View File

@@ -0,0 +1,212 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.wizardmanager;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.Xml;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class WizardScript implements Parcelable {
private static final String TAG = "WizardScript";
static final String WIZARD_SCRIPT_NAMESPACE =
"http://schemas.android.com/apk/res/com.google.android.setupwizard";
public static final String TAG_WIZARD_SCRIPT = "WizardScript";
public static final String TAG_WIZARD_ACTION = "WizardAction";
public static final String TAG_RESULT = "result";
public static final String ATTR_ID = "id";
public static final String ATTR_URI = "uri";
public static final String ATTR_ACTION = "action";
public static final String ATTR_FIRST_ACTION = "firstAction";
public static final String ATTR_RESULT_CODE = "resultCode";
private final Map<String, WizardAction> mActions;
private final String mFirstActionId;
public WizardScript(Map<String, WizardAction> actions, String firstActionId) {
mActions = Collections.unmodifiableMap(actions);
mFirstActionId = firstActionId;
}
public WizardAction getAction(String actionId) {
return mActions.get(actionId);
}
public WizardAction getFirstAction() {
return getAction(mFirstActionId);
}
public String getFirstActionId() {
return mFirstActionId;
}
public WizardAction getNextAction(String currentActionId, int resultCode) {
WizardAction wizardAction = null;
String nextActionId = getNextActionId(currentActionId, resultCode);
if (nextActionId != null) {
wizardAction = getAction(nextActionId);
}
return wizardAction;
}
public String getNextActionId(String currentActionId, int resultCode) {
String nextActionId = null;
if(resultCode != Activity.RESULT_CANCELED) {
WizardAction wizardAction = mActions.get(currentActionId);
if (LOGV) {
StringBuilder currentAction =
new StringBuilder().append("getNextActionId(").append(currentActionId)
.append(",").append(resultCode).append(")").append(" current uri=");
String uri = wizardAction == null ? "n/a" : wizardAction.getUri();
Log.v(TAG, currentAction.append(uri).toString());
}
nextActionId = wizardAction.getNextAction(resultCode);
} else {
if (LOGV) {
Log.v(TAG, "getNextActionId(" + currentActionId + "," + resultCode
+ ")" + " RESULT_CANCELED not expected; ignored");
}
}
return nextActionId;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mFirstActionId);
dest.writeTypedList(new ArrayList(this.mActions.values()));
}
public static final Creator<WizardScript> CREATOR = new Creator<WizardScript>() {
public WizardScript createFromParcel(Parcel source) {
String firstActionId = source.readString();
HashMap<String, WizardAction> actions = new HashMap();
ArrayList<WizardAction> actionList = new ArrayList();
source.readTypedList(actionList, WizardAction.CREATOR);
for (WizardAction action : actionList) {
actions.put(action.getId(), action);
}
return new WizardScript(actions, firstActionId);
}
public WizardScript[] newArray(int size) {
return new WizardScript[size];
}
};
public static WizardScript loadFromUri(Context context, String uriString) {
XmlPullParser xmlPullParser;
WizardScript wizardScript = null;
try {
ContentResolver.OpenResourceIdResult openResourceIdResult =
context.getContentResolver().getResourceId(Uri
.parse(uriString));
if("xml".equals(openResourceIdResult.r.getResourceTypeName(openResourceIdResult.id))) {
xmlPullParser =
openResourceIdResult.r.getXml(openResourceIdResult.id);
} else {
InputStream inputStream =
openResourceIdResult.r.openRawResource(openResourceIdResult.id);
xmlPullParser = Xml.newPullParser();
xmlPullParser.setInput(inputStream, null);
}
int next;
do {
next = xmlPullParser.next();
if (next == XmlPullParser.END_DOCUMENT) {
break;
}
}
while (next != XmlPullParser.START_TAG);
return parseWizardScript(xmlPullParser);
} catch (XmlPullParserException e) {
Log.e(TAG, "Ill-formatted wizard_script: " + uriString);
Log.e(TAG, e.getMessage());
return wizardScript;
} catch(FileNotFoundException fnfe) {
Log.e(TAG, "Cannot find file: " + uriString);
Log.e(TAG, fnfe.getMessage());
return wizardScript;
} catch(IOException ioe) {
Log.e(TAG, "Unable to read wizard_script: " + uriString);
Log.e(TAG, ioe.getMessage());
return wizardScript;
}
}
private static WizardScript parseWizardScript(XmlPullParser parser)
throws XmlPullParserException, IOException {
String startTag = parser.getName();
if(!TAG_WIZARD_SCRIPT.equals(startTag)) {
throw new XmlPullParserException("XML document must start with " +
"<WizardScript> tag; found "
+ startTag + " at " + parser.getPositionDescription());
}
String firstAction = parser.getAttributeValue(WIZARD_SCRIPT_NAMESPACE, ATTR_FIRST_ACTION);
if(firstAction == null) {
throw new XmlPullParserException("WizardScript must define a firstAction");
}
HashMap wizardActions = new HashMap();
int type;
final int depth = parser.getDepth();
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
final int next = parser.next();
if (next != XmlPullParser.END_TAG || next != XmlPullParser.TEXT) {
if (TAG_WIZARD_ACTION.equals(parser.getName())) {
WizardAction action = WizardAction.parseWizardAction(parser);
if (action != null) {
wizardActions.put(action.getId(), action);
}
} else {
XmlUtils.skipCurrentTag(parser);
}
}
}
return new WizardScript(wizardActions, firstAction);
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* Copyright (C) 2017 The LineageOS 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.cyanogenmod.setupwizard.wizardmanager;
import static com.cyanogenmod.setupwizard.SetupWizardApp.LOGV;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseArray;
import com.cyanogenmod.setupwizard.SetupWizardApp;
public class WizardTransitions extends SparseArray<String> implements Parcelable {
private static final String TAG = "WizardTransitions";
private String mDefaultAction;
public static final Creator<WizardTransitions> CREATOR = new Creator<WizardTransitions>() {
public WizardTransitions createFromParcel(Parcel source) {
WizardTransitions transitions = new WizardTransitions(source);
SparseArray<String> actions = source.readSparseArray(null);
for (int i = 0; i < actions.size(); i++) {
transitions.put(actions.keyAt(i), actions.valueAt(i));
}
return transitions;
}
public WizardTransitions[] newArray(int size) {
return new WizardTransitions[size];
}
};
public WizardTransitions() {}
public void setDefaultAction(String action) {
mDefaultAction = action;
}
public String getAction(int resultCode) {
return get(resultCode, mDefaultAction);
}
@Override
public void put(int key, String value) {
if (LOGV) {
Log.v(TAG, "put{" +
"key='" + key + '\'' +
", value=" + value +
'}');
}
super.put(key, value);
}
public String toString() {
return super.toString() + " mDefaultAction: " + mDefaultAction;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WizardTransitions that = (WizardTransitions) o;
return mDefaultAction != null ? mDefaultAction.equals(that.mDefaultAction) : that.mDefaultAction == null;
}
public int hashCode() {
return super.hashCode() + mDefaultAction.hashCode();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mDefaultAction);
int size = size();
SparseArray sparseArray = new SparseArray<>(size);
for (int i = 0; i < size; i++) {
sparseArray.put(keyAt(i), valueAt(i));
}
dest.writeSparseArray(sparseArray);
}
protected WizardTransitions(Parcel in) {
mDefaultAction = in.readString();
}
}

9
start_lineage_wizard.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
adb root
wait ${!}
adb shell pm disable com.google.android.setupwizard || true
wait ${!}
adb shell pm disable com.android.provision || true
wait ${!}
adb shell am start com.cyanogenmod.setupwizard/com.cyanogenmod.setupwizard.SetupWizardTestActivity

View File

@@ -0,0 +1,12 @@
#!/bin/bash
adb root
wait ${!}
adb shell pm enable com.google.android.setupwizard || true
wait ${!}
adb shell pm disable com.android.provision || true
wait ${!}
adb shell am start com.cyanogenmod.setupwizard/com.cyanogenmod.setupwizard.SetupWizardTestActivity
wait ${!}
sleep 1
adb shell am start com.google.android.setupwizard/com.google.android.setupwizard.SetupWizardTestActivity

View File

@@ -11,7 +11,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
# Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CyanogenSetupWizardTests
LOCAL_PACKAGE_NAME := LineageSetupWizardTests
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)

View File

@@ -1,171 +0,0 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.tests;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Toast;
import cyanogenmod.providers.CMSettings;
public class ManualTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cmaccount_test);
findViewById(R.id.enable_setup).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableSetup();
}
});
findViewById(R.id.enable_google_setup).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableGoogleSetup();
}
});
findViewById(R.id.setup_complete_flag).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setSetupComplete();
}
});
}
private void enableSetup() {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0);
CMSettings.Secure.putInt(getContentResolver(),
CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 0);
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
final PackageManager pm = getPackageManager();
ComponentName componentName = new ComponentName("com.cyanogenmod.setupwizard",
"com.cyanogenmod.setupwizard.ui.SetupWizardActivity");
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
componentName = new ComponentName("com.cyanogenmod.setupwizard",
"com.cyanogenmod.setupwizard.setup.FinishSetupReceiver");
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
pm.clearApplicationUserData("com.cyanogenmod.setupwizard", null);
ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.cyanogenmod.setupwizard");
try {
PackageInfo packageInfo = getPackageManager()
.getPackageInfo("com.google.android.setupwizard",
PackageManager.GET_ACTIVITIES |
PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES);
enableComponentArray(packageInfo.activities);
enableComponentArray(packageInfo.services);
enableComponentArray(packageInfo.receivers);
pm.clearApplicationUserData("com.google.android.setupwizard", null);
} catch (Exception e) {
Toast.makeText(this, "GMS not installed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
}
private void enableGoogleSetup() {
try {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0);
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
final PackageManager pm = getPackageManager();
PackageInfo packageInfo = this.getPackageManager()
.getPackageInfo("com.google.android.setupwizard",
PackageManager.GET_ACTIVITIES |
PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES);
enableComponentArray(packageInfo.activities);
enableComponentArray(packageInfo.services);
enableComponentArray(packageInfo.receivers);
pm.clearApplicationUserData("com.google.android.setupwizard", null);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
} catch (Exception e) {
Toast.makeText(this, "GMS not installed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
private void setSetupComplete() {
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
CMSettings.Secure.putInt(getContentResolver(),
CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 1);
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
final PackageManager pm = getPackageManager();
ComponentName componentName = new ComponentName("com.cyanogenmod.setupwizard",
"com.cyanogenmod.setupwizard.ui.SetupWizardActivity");
pm.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.cyanogenmod.setupwizard");
try {
PackageInfo packageInfo = this.getPackageManager()
.getPackageInfo("com.google.android.setupwizard",
PackageManager.GET_ACTIVITIES |
PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES);
enableComponentArray(packageInfo.activities);
enableComponentArray(packageInfo.services);
enableComponentArray(packageInfo.receivers);
pm.clearApplicationUserData("com.google.android.setupwizard", null);
} catch (Exception e) {
Toast.makeText(this, "GMS not installed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
}
private void enableComponentArray(ComponentInfo[] components) {
if(components != null) {
ComponentInfo[] componentInfos = components;
for(int i = 0; i < componentInfos.length; i++) {
enableComponent(componentInfos[i].packageName, componentInfos[i].name);
}
}
}
private void enableComponent(String packageName, String name) {
enableComponent(new ComponentName(packageName, name));
}
private void enableComponent(ComponentName component) {
getPackageManager().setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 1);
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2013 The CyanogenMod 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.cyanogenmod.setupwizard.tests;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.DONT_KILL_APP;
import static android.content.pm.PackageManager.GET_ACTIVITIES;
import static android.content.pm.PackageManager.GET_RECEIVERS;
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class ManualTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cmaccount_test);
findViewById(R.id.enable_setup).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableSetup();
}
});
findViewById(R.id.enable_google_setup).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
enableGoogleSetup();
}
});
findViewById(R.id.setup_complete_flag).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setSetupComplete();
}
});
}
private void enableSetup() {
try {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0);
final Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
resetComponentSets("com.cyanogenmod.setupwizard", GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES | MATCH_DISABLED_COMPONENTS);
resetComponentSets("com.google.android.setupwizard", GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES | MATCH_DISABLED_COMPONENTS);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
} catch (Exception e) {
Toast.makeText(this, "Error enabling setup " + e.toString(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
private void enableGoogleSetup() {
try {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 0);
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
resetComponentSets("com.google.android.setupwizard", GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES | MATCH_DISABLED_COMPONENTS);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
} catch (Exception e) {
Toast.makeText(this, "GMS not installed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
private void setSetupComplete() {
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
disableComponentSets("com.cyanogenmod.setupwizard", GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES);
try {
disableComponentSets("com.google.android.setupwizard", GET_ACTIVITIES |
GET_RECEIVERS | GET_SERVICES);
} catch (Exception e) {
Toast.makeText(this, "GMS not installed", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | intent.getFlags());
startActivity(intent);
finish();
}
private void disableComponentSets(String packageName, int flags) {
setComponentListEnabledState(getComponentSets(packageName, flags),
COMPONENT_ENABLED_STATE_DISABLED);
}
private void resetComponentSets(String packageName, int flags) {
setComponentListEnabledState(getComponentSets(packageName, flags),
COMPONENT_ENABLED_STATE_DEFAULT);
}
private void setComponentListEnabledState(List<ComponentName> componentNames,
int enabledState) {
for (ComponentName componentName : componentNames) {
Log.i("ManualTestActivity", " Changing component state " +
componentName.flattenToString() + " state=" + enabledState);
setComponentEnabledState(componentName, enabledState);
}
}
private void setComponentEnabledState(ComponentName componentName,
int enabledState) {
getPackageManager().setComponentEnabledSetting(componentName,
enabledState, DONT_KILL_APP);
}
private List<ComponentName> getComponentSets(String packageName, int flags) {
int i = 0;
List<ComponentName> componentNames = new ArrayList();
try {
PackageInfo allInfo = getPackageManager()
.getPackageInfo(packageName, flags);
if (allInfo != null) {
if (allInfo.activities != null && (flags & GET_ACTIVITIES) != 0) {
for (ComponentInfo info : allInfo.activities) {
componentNames.add(new ComponentName(packageName, info.name));
}
}
if (allInfo.receivers != null && (flags & GET_RECEIVERS) != 0) {
for (ComponentInfo info2 : allInfo.receivers) {
componentNames.add(new ComponentName(packageName, info2.name));
}
}
if (allInfo.services != null && (flags & GET_SERVICES) != 0) {
ServiceInfo[] serviceInfoArr = allInfo.services;
int length = serviceInfoArr.length;
while (i < length) {
componentNames.add(new ComponentName(packageName, serviceInfoArr[i].name));
i++;
}
}
}
} catch (PackageManager.NameNotFoundException e) {
}
return componentNames;
}
}