From 7710855b726a921d7fd1e85aeeb4b20fee998923 Mon Sep 17 00:00:00 2001 From: cretin45 Date: Thu, 7 May 2015 16:21:10 -0700 Subject: [PATCH] SetupWizard: Add kill switch implementation Change-Id: I1335cddf0dcc94eb8d2defeebdc47cb61abffd06 --- AndroidManifest.xml | 1 + res/drawable-hdpi/cross.png | Bin 0 -> 346 bytes res/drawable-hdpi/tick.png | Bin 0 -> 312 bytes res/drawable-mdpi/cross.png | Bin 0 -> 253 bytes res/drawable-mdpi/tick.png | Bin 0 -> 236 bytes res/drawable-xhdpi/cross.png | Bin 0 -> 422 bytes res/drawable-xhdpi/tick.png | Bin 0 -> 371 bytes res/drawable-xxhdpi/cross.png | Bin 0 -> 554 bytes res/drawable-xxhdpi/tick.png | Bin 0 -> 477 bytes res/drawable-xxxhdpi/cross.png | Bin 0 -> 692 bytes res/drawable-xxxhdpi/tick.png | Bin 0 -> 572 bytes res/layout/setup_cyanogen_services.xml | 52 ++++++++++++ res/values/strings.xml | 6 ++ .../setupwizard/SetupWizardApp.java | 14 ++++ .../setup/CyanogenServicesPage.java | 3 + .../setup/CyanogenSettingsPage.java | 23 +++++ .../setupwizard/setup/WelcomePage.java | 79 ++++++++++++++++-- .../setupwizard/util/SetupWizardUtils.java | 34 ++++++++ 18 files changed, 207 insertions(+), 5 deletions(-) create mode 100755 res/drawable-hdpi/cross.png create mode 100755 res/drawable-hdpi/tick.png create mode 100755 res/drawable-mdpi/cross.png create mode 100755 res/drawable-mdpi/tick.png create mode 100755 res/drawable-xhdpi/cross.png create mode 100755 res/drawable-xhdpi/tick.png create mode 100755 res/drawable-xxhdpi/cross.png create mode 100755 res/drawable-xxhdpi/tick.png create mode 100755 res/drawable-xxxhdpi/cross.png create mode 100755 res/drawable-xxxhdpi/tick.png diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d4a7826..d575831 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -47,6 +47,7 @@ + Px$6iGxuR5%fx)J+b8Fc5}e{ELZ+8<%Fv9m*~8nolSz;{OE+;kB2R{Rs>k&n}T0AmnSF(;^9!~g&Q07*qoM6N<$g2PjkIRF3v literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/tick.png b/res/drawable-hdpi/tick.png new file mode 100755 index 0000000000000000000000000000000000000000..1564a5b8686c6aa93771a454d054d1b37defc4f7 GIT binary patch literal 312 zcmV-80muG{P)Px#@<~KNR7efAltB)HFc3vS@1W6@VXN^NoYKcmU-CzeX)=f~nm9`CGP~T!J2?i- z0x7eFy>$mvF(Ji(*&u>xMvcrr7X!`$0WlbL49L#yP~}Px#w@E}nR45gll2Ho6Fc3tef*)E7;xUAR_dkT-DFneke_90RrQK3C8$<^tDcyaU zq)kdGHS$H?%HKo}z0F3$Sw6}q`60jMNCvek?f{=M(0-aD*dTgd@(qv#nrpC!uIlXp zQ4OZfnJg(o04s)t{OXhnh?kbgGxEtS#F^$Kn$UWjejk0J-|C}0M{`1LYcCLehJ*Cqb|WE(l*osaeN00000NkvXXu0mjf Dnto_@ literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/tick.png b/res/drawable-mdpi/tick.png new file mode 100755 index 0000000000000000000000000000000000000000..779b15940c6ac440c4c70f21151401acd934dfb2 GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&N!3HFiZux8nQjEnx?oJHr&dIz4a+Z0zIEHA5 zE}i7a*JL2zD){~Z>m9E>EfpM(?pX`1dvvdW%u$!R&c-s+VH7X3GT>2vwYb6tqBRxEpd(oH6v=%7Q9?@s9N kH?Etc`jPe9>~jjc!!mpo#V>711o?--)78&qol`;+00zcjApigX literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/cross.png b/res/drawable-xhdpi/cross.png new file mode 100755 index 0000000000000000000000000000000000000000..d5cac0a92ae2ab62ab72085a72574e35e74bff6d GIT binary patch literal 422 zcmV;X0a^ZuP)Px$U`a$lR7efI*3WJNArQxL|J-V??E`qN@BbwA+`D>RulDz4orFwS7*^sW0})t0 zLSVD|%^W*bKgx&lJ~s_3zckZPc~d_2D!@)kI=+>Yaumv(%>DVyDFiab0*hLq6R{#J2 literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/tick.png b/res/drawable-xhdpi/tick.png new file mode 100755 index 0000000000000000000000000000000000000000..0e10e6deda0995fc15a9f1d3059cc7f9d357cbec GIT binary patch literal 371 zcmV-(0gV2MP)|00001b5ch_0Itp) z=>Px$ElET{R7ef&*1ZmbFcbw~(CDCX*Tuon#aD1JzKV&DXnYX|-om(Yo z_Of`B1BF2Qr6MKE{`E5hE1cQO*|9VR+7oj^wn&Z?LxKb|1BA6f@=@8e-?*5sfYW4M zO_(bn7i&-}hBIRc>cm)ryf9WEZ;S;N$?NuCT+<>V@H; zvX%*EjdMHXhTIWN^~P{8f~LqBSt6_nqD4i)aBza2$O7SNE2Tk2!*Fo<$qKZ&jA&6& zF;x)TT2yq53(}yHVCq0VC_Zm|J;;|H?_rhSGw){jw(axdh;9!~*N@L}5)Av6huRsp zJZyTV_z$dBl$ntZ+d#ag4kh<;9~Hw6yFk3A2^AgV3#vmU!EhjL@j+*j)eG;Px$7}Kv@xN{X1k6%vs3z& z{EW>9W&JRXXW89Jo+Q7gr^5CgrKZ{&Mya)Bfb|dGY z9#|J-4YUXAhOC8JuuOYoP+siw*0~hj zi{4Vfa=dm@*Z}2X-j(ORkuHgpDuMta8u)hlJ+>?Iu13k;?8oRBkoB#j-07*qoM6N<$f_vWnYXATM literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/tick.png b/res/drawable-xxhdpi/tick.png new file mode 100755 index 0000000000000000000000000000000000000000..f398a15d63536ed909af052650ab21336caf7415 GIT binary patch literal 477 zcmV<30V4j1P)Px$mq|oHRA>e5*~?1BFc1dds^G%QTHU(Q2N7RI@DatQa4)#@9o+c;rE{nu?a5`5 z%zy(!+q8$wcX}h~H2sI^f8acY%GKy!)3oHxe1(uES04qXShZUnN!>UkL zVbv&$Fcp+Fm>S9wOciAXrjD`zYl0dLYlb2$Hf*^=J4dDLxK%VovFLE1DX1IldqjR9 ze~_Bd9K~YSFhN}`iYqL&aa~YrScqC|lP0bkip9%4_JDOcQ-YEuXMk$&xvnS{E|=mL z);Z|pEKe+I&RlmC0RrPX=i{_-Lr}!5Vcgcl4MW9XTDYO8Em$pXIBE}8iZg*a2Fu0q zQ;vKf;BR9wPiDq;Xt$-#D?X#+r=8BfmwkNaZACW}3kaWzTScWjE%~n7imoUYkqYCn z$8bC*7Tr-SA_vCfb8$mZC9oXaFjOfl1veB`1KYz5N7ce&I1?xqrWJh8G0ns;KAmgT Th@Si?00000NkvXXu0mjf6LZSL literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/cross.png b/res/drawable-xxxhdpi/cross.png new file mode 100755 index 0000000000000000000000000000000000000000..0a2800dd8de0f99cf061324fc2267d5b3ea1b8ce GIT binary patch literal 692 zcmV;l0!#ggP)Px%Zb?KzRA>d=+S^LQKoADts_2EM8^Mq8BQ~98>qY^n7cST9w zQF*8G%?Td^x#v(3fqBu9j63f#?mK9JWZ)RLuOAvY#&OQD9FPD?I9?!PPf9q>`G7?7 zk5sVFEkz_`3das0Z;<$w3idUOFGU1oE)I?_Dz8WyM@bwlqa(GrXEJTM*P#Yj?!gW~goKQU>ob<`3>k}@P)Px$_DMuRRA>e5+DlHuFc1dd0(Sth?UskQ0}_{L_uLV247MDDHO!AXRnt07Y>y{1 zc7AD;q|VD<-6~D9*{oRwR)KPX8`{N7Xg6r+Juui)y;5CKeN!FNI}qbM97MJ>9U%1# zbdJNLW`NWy&=}4IQjb7WI0K|>Ug~5z7w5=15go8 z>p;agEdz<*v4PHRBoI4uEH!D$7k8cqv9RdKunRmbrRq=MrWNDap$kSdNh zAaxv1K#Smb0a^?PK(Tw$Pt?An!U-;wMRCySvCcnI8~$y)KhzgZf2lOHI1V}+0%9B< zUAMFzpfr(8;DmtAaj*`eiDU)`9X}mGV>nn3(LgeVgHAKh9nHT}@y7~nq0~e&hXVix z`k{H?Z1LhmY9N`!fdd0!9?!+#e==<(vp7IG1;Vm6l4+a}kS3COoG~B`Bo{a_pqfZ- zaHfE2Ai2Vs10;#$4reZq1d>af6rd6$T!7-v06%JreZ}(sWLInj%{IKVDapA`dZq)o z!~sky5VlE0!cUVqF*S1dgmZwfZ3+?}D>gNWgA>jL!nRUKW^qb^B#=zwNC1@}na7a= z%0Y60BMFp((vanO<4d7}fM+~yB1vy{5fNa{iW0000< KMNUMnLSTX#{pA(_ literal 0 HcmV?d00001 diff --git a/res/layout/setup_cyanogen_services.xml b/res/layout/setup_cyanogen_services.xml index ba16627..36837bb 100644 --- a/res/layout/setup_cyanogen_services.xml +++ b/res/layout/setup_cyanogen_services.xml @@ -50,6 +50,58 @@ android:text="@string/services_explanation" android:clickable="true"/> + + + + + + + + + + + + + + Use on screen navigation keys instead of hardware keys. Use secure SMS %s to encrypt SMS conversations with other users using secure SMS on a %s device. + + Unlock + This device has been locked by the user. + Require your Cyanogen OS account password in order to use your device even after a factory reset. + To turn this feature off/on, please go to Settings > Security + Without a Cyanogen OS Account, you won\'t be able to:\n\nCustomize your phone with new icons, wallpapers and more in the Themes app\n\nLocate or remotely erase your phone if it\'s lost diff --git a/src/com/cyanogenmod/setupwizard/SetupWizardApp.java b/src/com/cyanogenmod/setupwizard/SetupWizardApp.java index a1d644b..82b466d 100644 --- a/src/com/cyanogenmod/setupwizard/SetupWizardApp.java +++ b/src/com/cyanogenmod/setupwizard/SetupWizardApp.java @@ -34,6 +34,7 @@ public class SetupWizardApp extends Application { public static final String ACTION_FINISHED = "com.cyanogenmod.setupwizard.SETUP_FINISHED"; + public static final String ACCOUNT_TYPE_CYANOGEN = "com.cyanogen"; public static final String ACCOUNT_TYPE_GMS = "com.google"; public static final String ACTION_SETUP_WIFI = "com.android.net.wifi.SETUP_WIFI_NETWORK"; @@ -46,6 +47,8 @@ public class SetupWizardApp extends Application { public static final String EXTRA_USE_IMMERSIVE = "useImmersiveMode"; public static final String EXTRA_THEME = "theme"; public static final String EXTRA_MATERIAL_LIGHT = "material_light"; + public static final String EXTRA_CKSOP = "cksOp"; + public static final String EXTRA_LOGIN_FOR_KILL_SWITCH = "authCks"; private static final String KEY_DETECT_CAPTIVE_PORTAL = "captive_portal_detection_enabled"; @@ -61,11 +64,14 @@ public class SetupWizardApp extends Application { public static final int REQUEST_CODE_SETUP_CYANOGEN= 3; 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 RADIO_READY_TIMEOUT = 10 * 1000; private boolean mIsRadioReady = false; + private boolean mIsAuthorized = false; + private StatusBarManager mStatusBarManager; private final Handler mHandler = new Handler(); @@ -114,6 +120,14 @@ public class SetupWizardApp extends Application { mIsRadioReady = radioReady; } + public boolean isAuthorized() { + return mIsAuthorized; + } + + public void setIsAuthorized(boolean isAuthorized) { + mIsAuthorized = isAuthorized; + } + public void disableStatusBar() { mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND | StatusBarManager.DISABLE_NOTIFICATION_ALERTS | StatusBarManager.DISABLE_NOTIFICATION_TICKER | StatusBarManager.DISABLE_RECENT | StatusBarManager.DISABLE_HOME diff --git a/src/com/cyanogenmod/setupwizard/setup/CyanogenServicesPage.java b/src/com/cyanogenmod/setupwizard/setup/CyanogenServicesPage.java index 479f2be..e71dd79 100644 --- a/src/com/cyanogenmod/setupwizard/setup/CyanogenServicesPage.java +++ b/src/com/cyanogenmod/setupwizard/setup/CyanogenServicesPage.java @@ -101,6 +101,9 @@ public class CyanogenServicesPage extends SetupPage { resultCode == Activity.RESULT_OK ? "success" : "skipped"); if (SetupWizardUtils.accountExists(mContext, mContext.getString(R.string.cm_account_type))) { + if (SetupWizardUtils.isDeviceLocked()) { + ((SetupWizardApp) mContext.getApplicationContext()).setIsAuthorized(true); + } setHidden(true); } getCallbacks().onNextPage(); diff --git a/src/com/cyanogenmod/setupwizard/setup/CyanogenSettingsPage.java b/src/com/cyanogenmod/setupwizard/setup/CyanogenSettingsPage.java index bdc3076..86906da 100644 --- a/src/com/cyanogenmod/setupwizard/setup/CyanogenSettingsPage.java +++ b/src/com/cyanogenmod/setupwizard/setup/CyanogenSettingsPage.java @@ -42,6 +42,7 @@ import android.view.IWindowManager; import android.view.View; import android.view.WindowManagerGlobal; import android.widget.CheckBox; +import android.widget.ImageView; import android.widget.TextView; import com.cyanogenmod.setupwizard.R; @@ -213,6 +214,9 @@ public class CyanogenSettingsPage extends SetupPage { public static class CyanogenSettingsFragment extends SetupPageFragment { + private View mKillSwitchView; + private TextView mKillSwitchTitle; + private ImageView mKillSwitchStatus; private View mMetricsRow; private View mDefaultThemeRow; private View mNavKeysRow; @@ -287,6 +291,21 @@ public class CyanogenSettingsPage extends SetupPage { privacyPolicy.setMovementMethod(LinkMovementMethod.getInstance()); privacyPolicy.setText(ss); + mKillSwitchView = mRootView.findViewById(R.id.killswitch); + mKillSwitchTitle = (TextView)mRootView.findViewById(R.id.killswitch_title); + mKillSwitchStatus = (ImageView)mRootView.findViewById(R.id.killswitch_check); + if (hideKillSwitch()) { + mKillSwitchView.setVisibility(View.GONE); + } else { + if (SetupWizardUtils.isDeviceLocked()) { + mKillSwitchTitle.setEnabled(true); + mKillSwitchStatus.setImageResource(R.drawable.tick); + } else { + mKillSwitchTitle.setEnabled(false); + mKillSwitchStatus.setImageResource(R.drawable.cross); + } + } + mMetricsRow = mRootView.findViewById(R.id.metrics); mMetricsRow.setOnClickListener(mMetricsClickListener); String metricsHelpImproveCM = @@ -414,5 +433,9 @@ public class CyanogenSettingsPage extends SetupPage { } } + private static boolean hideKillSwitch() { + return !SetupWizardUtils.hasKillSwitch(); + } + } } diff --git a/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java b/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java index 1f63878..3f01e53 100644 --- a/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java +++ b/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java @@ -16,6 +16,10 @@ package com.cyanogenmod.setupwizard.setup; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.app.Activity; import android.app.ActivityOptions; import android.app.Fragment; import android.app.FragmentManager; @@ -25,14 +29,17 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import android.view.View; import android.widget.ArrayAdapter; import android.widget.NumberPicker; import com.cyanogenmod.setupwizard.R; +import com.cyanogenmod.setupwizard.SetupWizardApp; import com.cyanogenmod.setupwizard.cmstats.SetupStats; import com.cyanogenmod.setupwizard.ui.LocalePicker; import com.cyanogenmod.setupwizard.ui.SetupPageFragment; +import com.cyanogenmod.setupwizard.util.SetupWizardUtils; import java.util.Locale; @@ -42,21 +49,23 @@ public class WelcomePage extends SetupPage { 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) { - Fragment fragment = fragmentManager.findFragmentByTag(getKey()); - if (fragment == null) { + 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); - fragment = new WelcomeFragment(); - fragment.setArguments(args); + mWelcomeFragment = new WelcomeFragment(); + mWelcomeFragment.setArguments(args); } - return fragment; + return mWelcomeFragment; } @Override @@ -64,6 +73,16 @@ public class WelcomePage extends SetupPage { return R.string.setup_welcome; } + @Override + public boolean doNextAction() { + if (isLocked()) { + confirmCyanogenCredentials(mWelcomeFragment); + return true; + } else { + return super.doNextAction(); + } + } + @Override public boolean doPreviousAction() { Intent intent = new Intent(ACTION_EMERGENCY_DIAL); @@ -81,16 +100,66 @@ public class WelcomePage extends SetupPage { 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() { + if (isLocked()) { + return R.string.setup_unlock; + } else { + return R.string.next; + } + } + @Override public int getPrevButtonTitleResId() { return R.string.emergency_call; } + private void confirmCyanogenCredentials(final Fragment fragment) { + AccountManager accountManager = AccountManager.get(mContext); + accountManager.editProperties(SetupWizardApp.ACCOUNT_TYPE_CYANOGEN, null, + new AccountManagerCallback() { + public void run(AccountManagerFuture f) { + try { + Bundle b = f.getResult(); + Intent i = b.getParcelable(AccountManager.KEY_INTENT); + i.putExtra(SetupWizardApp.EXTRA_FIRST_RUN, true); + i.putExtra(SetupWizardApp.EXTRA_SHOW_BUTTON_BAR, true); + i.putExtra(SetupWizardApp.EXTRA_USE_IMMERSIVE, true); + i.putExtra(SetupWizardApp.EXTRA_LOGIN_FOR_KILL_SWITCH, true); + fragment.startActivityForResult(i, + SetupWizardApp.REQUEST_CODE_UNLOCK); + } catch (Throwable t) { + Log.e(getKey(), "confirmCredentials failed", t); + } + } + }, null); + } + + private boolean isLocked() { + boolean isAuthorized = ((SetupWizardApp) mContext.getApplicationContext()).isAuthorized(); + if (SetupWizardUtils.isDeviceLocked()) { + return !isAuthorized; + } + return false; + } + public static class WelcomeFragment extends SetupPageFragment { private ArrayAdapter mLocaleAdapter; diff --git a/src/com/cyanogenmod/setupwizard/util/SetupWizardUtils.java b/src/com/cyanogenmod/setupwizard/util/SetupWizardUtils.java index 19ce2e8..113e204 100644 --- a/src/com/cyanogenmod/setupwizard/util/SetupWizardUtils.java +++ b/src/com/cyanogenmod/setupwizard/util/SetupWizardUtils.java @@ -17,6 +17,7 @@ package com.cyanogenmod.setupwizard.util; import android.accounts.AccountManager; +import android.app.AppGlobals; import android.content.ComponentName; import android.content.Context; import android.content.pm.ComponentInfo; @@ -25,6 +26,8 @@ import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiManager; +import android.os.IBinder; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.telephony.ServiceState; @@ -32,6 +35,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.internal.os.IKillSwitchService; import com.cyanogenmod.setupwizard.SetupWizardApp; import com.google.android.gms.common.ConnectionResult; @@ -124,6 +128,36 @@ public class SetupWizardUtils { 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 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()) {